<!DOCTYPE html>



  


<html class="theme-next gemini use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">
<script>
    (function () {
        if ('') {
            if (prompt('请输入文章密码') !== '') {
                alert('密码错误！');
                if (history.length === 1) {
                    location.replace("https://google.com"); // 这里替换成你的首页
                } else {
                    history.back();
                }
            }
        }
    })();
</script>








<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="mysql,">










<meta name="description" content="Mysql使用别名多表查询join时问题12345SELECT * FROM t1, t2 LEFT JOIN t3 ON (t1.id=t3.id) WHERE t1.id=t2.id但是在执行的时候报错“Unknown column t1.id”,以前博主习惯利用AS 表别名来进行多表关联查询，这让博主很凌乱，一时不知道如何下手解决了实际上执行 SELECT * FROM t1,( t2 LE">
<meta name="keywords" content="mysql">
<meta property="og:type" content="article">
<meta property="og:title" content="mysql片段收集">
<meta property="og:url" content="http://yoursite.com/2019/01/07/mysql片段收集/index.html">
<meta property="og:site_name" content="苏生不惑的博客">
<meta property="og:description" content="Mysql使用别名多表查询join时问题12345SELECT * FROM t1, t2 LEFT JOIN t3 ON (t1.id=t3.id) WHERE t1.id=t2.id但是在执行的时候报错“Unknown column t1.id”,以前博主习惯利用AS 表别名来进行多表关联查询，这让博主很凌乱，一时不知道如何下手解决了实际上执行 SELECT * FROM t1,( t2 LE">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="https://iocaffcdn.phphub.org/uploads/images/201904/24/27516/LoRNLmbvjW.png!large">
<meta property="og:image" content="https://iocaffcdn.phphub.org/uploads/images/201904/24/27516/DnQMqeCmUn.png!large">
<meta property="og:updated_time" content="2020-04-23T09:21:34.678Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="mysql片段收集">
<meta name="twitter:description" content="Mysql使用别名多表查询join时问题12345SELECT * FROM t1, t2 LEFT JOIN t3 ON (t1.id=t3.id) WHERE t1.id=t2.id但是在执行的时候报错“Unknown column t1.id”,以前博主习惯利用AS 表别名来进行多表关联查询，这让博主很凌乱，一时不知道如何下手解决了实际上执行 SELECT * FROM t1,( t2 LE">
<meta name="twitter:image" content="https://iocaffcdn.phphub.org/uploads/images/201904/24/27516/LoRNLmbvjW.png!large">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Gemini',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://yoursite.com/2019/01/07/mysql片段收集/">



<meta name="referrer" content="never"> ​​​​


  <title>mysql片段收集 | 苏生不惑的博客</title>
  








</head>

<body itemscope="" itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope="" itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">苏生不惑的博客</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br>
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            归档
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="popup-trigger">
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br>
            
            搜索
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <div class="popup search-popup local-search-popup">
  <div class="local-search-header clearfix">
    <span class="search-icon">
      <i class="fa fa-search"></i>
    </span>
    <span class="popup-btn-close">
      <i class="fa fa-times-circle"></i>
    </span>
    <div class="local-search-input-wrapper">
      <input autocomplete="off" placeholder="搜索..." spellcheck="false" type="text" id="local-search-input">
    </div>
  </div>
  <div id="local-search-result"></div>
</div>



    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope="" itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2019/01/07/mysql片段收集/">

    <span hidden itemprop="author" itemscope="" itemtype="http://schema.org/Person">
      <meta itemprop="name" content="苏生不惑">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope="" itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="苏生不惑的博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">mysql片段收集</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-01-07T15:13:54+08:00">
                2019-01-07
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          
            <span class="post-meta-divider">|</span>
            <span class="page-pv"><i class="fa fa-file-o"></i>
            <span class="busuanzi-value" id="busuanzi_value_page_pv"></span>次
            </span>
          

          
            <div class="post-wordcount">
              
                
                  <span class="post-meta-divider">|</span>
                
                <span class="post-meta-item-icon">
                  <i class="fa fa-file-word-o"></i>
                </span>
                
                  <span class="post-meta-item-text">字数统计&#58;</span>
                
                <span title="字数统计">
                  41.1k 字
                </span>
              

              
                <span class="post-meta-divider">|</span>
              

              
                <span class="post-meta-item-icon">
                  <i class="fa fa-clock-o"></i>
                </span>
                
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                
                <span title="阅读时长">
                  191 分钟
                </span>
              
            </div>
          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h3 id="Mysql使用别名多表查询join时问题"><a href="#Mysql使用别名多表查询join时问题" class="headerlink" title="Mysql使用别名多表查询join时问题"></a>Mysql使用别名多表查询join时问题</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">SELECT * FROM t1, t2 LEFT JOIN t3 ON (t1.id=t3.id) WHERE t1.id=t2.id</span><br><span class="line">但是在执行的时候报错“Unknown column t1.id”,以前博主习惯利用AS 表别名来进行多表关联查询，这让博主很凌乱，一时不知道如何下手解决了</span><br><span class="line">实际上执行 SELECT * FROM t1,( t2 LEFT JOIN t3 ON (t1.id=t3.id)) WHERE t1.id=t2.id</span><br><span class="line"></span><br><span class="line">SELECT * FROM t1 INNER JOIN t2 LEFT JOIN t3 ON (t1.id=t3.id) WHERE t1.id=t2.id</span><br></pre></td></tr></table></figure>
<h3 id="重置root密码"><a href="#重置root密码" class="headerlink" title="重置root密码"></a>重置root密码</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line">kill <span class="string">`cat /mysql-data-directory/host_name.pid`</span></span><br><span class="line">#ps方法</span><br><span class="line">ps aux|grep <span class="string">'mysql'</span></span><br><span class="line">#这里把%pid%替换为上面ps给的进程id</span><br><span class="line">sudo kill %pid%</span><br><span class="line">#5.7.6和以后版本</span><br><span class="line">ALTER USER <span class="string">'root'</span>@<span class="string">'localhost'</span> IDENTIFIED BY <span class="string">'MyNewPass'</span>;</span><br><span class="line">#5.7.6以前版本</span><br><span class="line">SET PASSWORD FOR <span class="string">'root'</span>@<span class="string">'localhost'</span> = PASSWORD(<span class="string">'MyNewPass'</span>);</span><br><span class="line">#官网手册命令，mac用户不推荐</span><br><span class="line"> </span><br><span class="line">mysqld_safe --init-file=<span class="regexp">/home/m</span>e/mysql-init &amp;</span><br><span class="line"> </span><br><span class="line">#mac用户推荐命令</span><br><span class="line"> </span><br><span class="line">sudo /usr/local/mysql/bin/mysqld --user=_mysql --basedir=<span class="regexp">/usr/</span>local/mysql --datadir=<span class="regexp">/usr/</span>local/mysql/data --plugin-dir=<span class="regexp">/usr/</span>local/mysql/lib/plugin --log-error=<span class="regexp">/usr/</span>local/mysql/data/mysqld.local.err --pid-file=<span class="regexp">/usr/</span>local/mysql/data/mysqld.local.pid --init-file=<span class="regexp">/Users/</span>king/sql/alter_root.sql &amp;</span><br><span class="line"><span class="number">1.</span> 停止mysql服务:</span><br><span class="line">systemctl stop mysqld</span><br><span class="line"></span><br><span class="line"><span class="number">2.</span> 设置mysql的环境变量参数 </span><br><span class="line">systemctl set-environment MYSQLD_OPTS=<span class="string">"--skip-grant-tables"</span></span><br><span class="line"></span><br><span class="line"><span class="number">3.</span> 启动mysql服务</span><br><span class="line">systemctl start mysqld</span><br><span class="line"></span><br><span class="line"><span class="number">4.</span> root无密码登录</span><br><span class="line">mysql -u root</span><br><span class="line"></span><br><span class="line"><span class="number">5.</span> 更新root密码</span><br><span class="line">mysql&gt; UPDATE mysql.user SET authentication_string = PASSWORD(<span class="string">'MyNewPassword'</span>)</span><br><span class="line">    -&gt; WHERE User = <span class="string">'root'</span> AND Host = <span class="string">'localhost'</span>;</span><br><span class="line">mysql&gt; FLUSH PRIVILEGES;</span><br><span class="line">mysql&gt; quit</span><br><span class="line"></span><br><span class="line"><span class="number">6.</span> 关闭mysql服务</span><br><span class="line">systemctl stop mysqld</span><br><span class="line"></span><br><span class="line"><span class="number">7.</span> 删除mysql环境参数</span><br><span class="line">systemctl unset-environment MYSQLD_OPTS</span><br><span class="line"></span><br><span class="line"><span class="number">8.</span> 再次启动:</span><br><span class="line">systemctl start mysqld</span><br><span class="line"></span><br><span class="line"><span class="number">9.</span> 用root登录:</span><br><span class="line">. mysql -u root -p</span><br></pre></td></tr></table></figure>
<h3 id="mysql5-7无法远程连接问题"><a href="#mysql5-7无法远程连接问题" class="headerlink" title="mysql5.7无法远程连接问题"></a>mysql5.7无法远程连接问题</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">mysql -uroot -p</span><br><span class="line"> </span><br><span class="line">use mysql;</span><br><span class="line"> </span><br><span class="line">select * <span class="keyword">from</span> user\G;</span><br><span class="line">sudo iptables -L #查看防火墙规则列表</span><br><span class="line"> </span><br><span class="line">sudo iptables -F  #清空防火墙列表</span><br><span class="line">vi /etc/mysql/mysql.conf.d/mysqld.cnf</span><br><span class="line">#bind-address = 127.0.0.1</span><br><span class="line">bind-address = <span class="number">0.0</span><span class="number">.0</span><span class="number">.0</span></span><br></pre></td></tr></table></figure>
<h3 id="select-导致的mysql线程sending-data"><a href="#select-导致的mysql线程sending-data" class="headerlink" title="select *导致的mysql线程sending data"></a>select *导致的mysql线程sending data</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">当有大量的”select * <span class="keyword">from</span> xxx”存在时，虽然这个表的数据量不是很大，只有区区几千条记录记录，但是大量的查询引起mysql线程状态卡在”sending data”时，服务器的负载就上来了。</span><br><span class="line"></span><br><span class="line">那么什么是”sending data”状态哪?其实这是一个很容易引起误导的状态说明，”sending data”是包含读取数据+发送数据的。这里以innodb存储引擎来说，我们在使用索引找到我们所需的记录时，期初得到是索引列信息和主键信息，如果我们查询的信息索引列中已经包含，那么万事大吉，mysql会把这些信息发送给客户端。但是如果像我的例子中的是使用”select *”这种情况，或者要索引列中未包含我们需要需要的更多信息，那么这时mysql就会拿着主键id去数据行获取信息，然后再把些信息发送给客户端。</span><br><span class="line"></span><br><span class="line">现在回到上面的问题，我们数据表记录数不多，为什么会引起”sending data”哪?我们活动信息表有几个字段是MEDIUMTEXT或者VARCHAR(<span class="number">3000</span>)类似这种要存储比较长字符串内容的字段，所以在使用”select *”时我们把本来不需要，但是却占用很大空间的字段也返回了，造成了大量无用的IO操作，这里包含读取数据和发送数据。由于接口我们使用的是被动缓存，所以活动刚开始时这些请求都打到了数据库，后面接口缓存生效以后数据库压力就降下来了。</span><br><span class="line"></span><br><span class="line">开发框架使用的是Lumen,而且我们主要使用的是里面的ORM-Elopment,有些地方没有注意查询时设定字段就引起了这个问题，说句实话以前在使用ORM时，我一直没有养成限制返回字段的习惯。希望看到这篇文章的同学也能引以为戒，以后尽量不要使用”seleect *”这样粗暴的查询方式。</span><br></pre></td></tr></table></figure>
<h3 id="lumen数据库时区设置"><a href="#lumen数据库时区设置" class="headerlink" title="lumen数据库时区设置"></a>lumen数据库时区设置</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">http:<span class="comment">//www.helpergarden.com/2018/05/lumen%e6%95%b0%e6%8d%ae%e5%ba%93%e6%97%b6%e5%8c%ba%e8%ae%be%e7%bd%ae.html</span></span><br><span class="line">timestamp里面居然保存的居然是带时区的</span><br><span class="line">查看ORM源码，它的注释里面说日期类型的字符创会转化成“DateTime/Carbon”实例，然后再进一步处理是输出或者存入数据库。</span><br><span class="line"></span><br><span class="line">我们可以通过在.env中设置”DB_TIMEZONE”来解决时区不一致的问题。</span><br><span class="line"></span><br><span class="line">DB_TIMEZONE=+<span class="number">8</span>:<span class="number">00</span></span><br><span class="line">一般来说要保证我们设置DB_TIMEZONE和APP_TIMEZONE一致的，所以一般配置文件都是这样的。</span><br><span class="line"></span><br><span class="line">APP_TIMEZONE=Asia/Shanghai</span><br><span class="line">DB_TIMEZONE=+<span class="number">8</span>:<span class="number">00</span></span><br></pre></td></tr></table></figure>
<h3 id="nginx跨域设置"><a href="#nginx跨域设置" class="headerlink" title="nginx跨域设置"></a>nginx跨域设置</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">location / &#123;</span><br><span class="line">       index  index.html index.htm index.php;</span><br><span class="line">       autoindex on;</span><br><span class="line">       try_files $uri $uri/ <span class="regexp">/index.php?$query_string;</span></span><br><span class="line"><span class="regexp">&#125;</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">include cors.conf;</span></span><br><span class="line"><span class="regexp">vi cors.conf </span></span><br><span class="line"><span class="regexp">add_header Access-Control-Allow-Origin *;</span></span><br><span class="line"><span class="regexp">add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';</span></span><br><span class="line"><span class="regexp">add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">if ($request_method = 'OPTIONS') &#123;</span></span><br><span class="line"><span class="regexp">    return 204;</span></span><br><span class="line"><span class="regexp">&#125;</span></span><br></pre></td></tr></table></figure>
<h3 id="swoole-process父子进程使用队列通信"><a href="#swoole-process父子进程使用队列通信" class="headerlink" title="swoole process父子进程使用队列通信"></a>swoole process父子进程使用队列通信</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line">&lt;?php</span><br><span class="line"><span class="comment">//http://www.helpergarden.com/2018/05/swoole-process%e7%88%b6%e5%ad%90%e8%bf%9b%e7%a8%8b%e4%bd%bf%e7%94%a8%e9%98%9f%e5%88%97%e9%80%9a%e4%bf%a1.html</span></span><br><span class="line">$worker_num = <span class="number">2</span>;</span><br><span class="line">$process_pool = [];</span><br><span class="line"></span><br><span class="line">$process= <span class="literal">null</span>;</span><br><span class="line">$pid = posix_getpid();</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sub_process</span>(<span class="params">swoole_process $worker</span>)</span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    sleep(<span class="number">1</span>); <span class="comment">//防止父进程还未往消息队列中加入内容直接退出</span></span><br><span class="line">    echo <span class="string">"worker "</span>.$worker-&gt;pid.<span class="string">" started"</span>.PHP_EOL;</span><br><span class="line">    <span class="keyword">while</span>($msg = $worker-&gt;pop())&#123;</span><br><span class="line">        <span class="keyword">if</span> ($msg === <span class="literal">false</span>) &#123;</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        $sub_pid = $worker-&gt;pid;</span><br><span class="line">        echo <span class="string">"[$sub_pid] msg : $msg"</span>.PHP_EOL;</span><br><span class="line">        sleep(<span class="number">1</span>);<span class="comment">//这里的sleep模拟必须，否则可能1个worker就把所有信息全接受了</span></span><br><span class="line">    &#125;</span><br><span class="line">    echo <span class="string">"worker "</span>.$worker-&gt;pid.<span class="string">" exit"</span>.PHP_EOL;</span><br><span class="line">    $worker-&gt;exit(<span class="number">0</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">$customMsgKey = <span class="number">1</span>;<span class="comment">//默认为空，这个地方可以随便填的</span></span><br><span class="line">$mod = <span class="number">2</span> | swoole_process::IPC_NOWAIT;<span class="comment">//这里设置队列为非阻塞模式</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//创建worker进程</span></span><br><span class="line"><span class="keyword">for</span>($i=<span class="number">0</span>;$i&lt;$worker_num; $i++) &#123;</span><br><span class="line">    $process=<span class="keyword">new</span> swoole_process(<span class="string">'sub_process'</span>);</span><br><span class="line">    $process-&gt;useQueue($customMsgKey, $mod);</span><br><span class="line">    $process-&gt;start();</span><br><span class="line">    $pid = $process-&gt;pid;</span><br><span class="line">    $process_pool[$pid] = $process;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">$messages = [</span><br><span class="line">    <span class="string">"Hello World!"</span>,</span><br><span class="line">    <span class="string">"Hello Cat!"</span>,</span><br><span class="line">    <span class="string">"Hello King"</span>,</span><br><span class="line">    <span class="string">"Hello Leon"</span>,</span><br><span class="line">    <span class="string">"Hello Rose"</span></span><br><span class="line">];</span><br><span class="line"><span class="comment">//由于所有进程是共享使用1个消息队列，所以只需向一个字进程发送消息即可</span></span><br><span class="line">$process = current($process_pool);</span><br><span class="line">foreach ($messages <span class="keyword">as</span> $msg) &#123;</span><br><span class="line">    $process-&gt;push($msg);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">swoole_process::wait();</span><br><span class="line">swoole_process::wait();</span><br><span class="line"></span><br><span class="line">echo <span class="string">"master exit"</span>.PHP_EOL;</span><br></pre></td></tr></table></figure>
<h3 id="yum安装elasticsearch"><a href="#yum安装elasticsearch" class="headerlink" title="yum安装elasticsearch"></a>yum安装elasticsearch</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//http://www.helpergarden.com/2018/03/yum%e5%ae%89%e8%a3%85elasticsearch.html</span></span><br><span class="line">yum install java</span><br><span class="line">yum makecache</span><br><span class="line">yum install elasticsearch</span><br><span class="line">cd /usr/share/elasticsearch</span><br><span class="line">./bin/elasticsearch-plugin install https:<span class="comment">//github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.2.2/elasticsearch-analysis-ik-6.2.2.zip</span></span><br><span class="line">  systemctl start elasticsearch</span><br><span class="line">curl http:<span class="comment">//127.0.0.1:9200</span></span><br><span class="line">访问“http:<span class="comment">//127.0.0.1:9200/_cat/plugins”可以查看es安装的插件。</span></span><br><span class="line"></span><br><span class="line">curl http:<span class="comment">//127.0.0.1:9200/_cat/plugins</span></span><br></pre></td></tr></table></figure>
<h3 id="grant"><a href="#grant" class="headerlink" title="grant"></a>grant</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt;grant select,<span class="keyword">delete</span>,update,create,drop on *.* to test@<span class="string">"%"</span> identified by <span class="string">"1234"</span>;</span><br><span class="line"></span><br><span class="line">     <span class="comment">//test用户对所有数据库都有select,delete,update,create,drop 权限。https://laravel-china.org/articles/22147</span></span><br><span class="line">　 @<span class="string">"%"</span> 表示对所有非本地主机授权，不包括localhost。</span><br><span class="line"></span><br><span class="line">　对localhost授权：加上一句grant all privileges on testDB.* to test@localhost identified by <span class="string">'1234'</span>;即可</span><br></pre></td></tr></table></figure>
<h3 id="EXPLAIN-查看SQL执行计划"><a href="#EXPLAIN-查看SQL执行计划" class="headerlink" title="EXPLAIN 查看SQL执行计划"></a>EXPLAIN 查看SQL执行计划</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">EXPLAIN SELECT ……</span><br><span class="line">EXPLAIN EXTENDED SELECT ……</span><br><span class="line">将执行计划<span class="string">"反编译"</span>成SELECT语句，运行SHOW WARNINGS，可得到被MySQL优化器优化后的查询语句。</span><br><span class="line">EXPLAIN PARTITIONS SELECT ……</span><br><span class="line">用于分区表的EXPLAIN生成QEP的信息</span><br></pre></td></tr></table></figure>
<h3 id="卸载mysql8"><a href="#卸载mysql8" class="headerlink" title="卸载mysql8"></a>卸载mysql8</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">[root@VM_0_14_centos ~]# rpm -qa|grep mysql</span><br><span class="line"></span><br><span class="line">mysql80-community-release-el7<span class="number">-1.</span>noarch</span><br><span class="line">mysql-community-client<span class="number">-8.0</span><span class="number">.13</span><span class="number">-1.</span>el7.x86_64</span><br><span class="line">mysql-community-libs<span class="number">-8.0</span><span class="number">.13</span><span class="number">-1.</span>el7.x86_64</span><br><span class="line">mysql-community-libs-compat<span class="number">-8.0</span><span class="number">.13</span><span class="number">-1.</span>el7.x86_64</span><br><span class="line">php70w-mysqlnd<span class="number">-7.0</span><span class="number">.32</span><span class="number">-1.</span>w7.x86_64</span><br><span class="line">mysql-community-common<span class="number">-8.0</span><span class="number">.13</span><span class="number">-1.</span>el7.x86_64</span><br><span class="line">mysql-community-server<span class="number">-8.0</span><span class="number">.13</span><span class="number">-1.</span>el7.x86_64</span><br><span class="line"></span><br><span class="line">yum remove mysql80-community-release-el7<span class="number">-1.</span>noarch</span><br><span class="line">[root@VM_0_14_centos ~]# find / -name mysql</span><br><span class="line">/etc/selinux/targeted/tmp/modules/<span class="number">100</span>/mysql</span><br><span class="line">/etc/selinux/targeted/active/modules/<span class="number">100</span>/mysql</span><br><span class="line">/<span class="keyword">var</span>/lib/mysql</span><br><span class="line">/<span class="keyword">var</span>/lib/mysql/mysql</span><br><span class="line">/<span class="keyword">var</span>/lib/docker/volumes/<span class="number">68</span>a07333528e60edd5980282ae6b0a3ce2324021eb8ca2f1963adb5a199ade7a/_data/mysql</span><br><span class="line">/<span class="keyword">var</span>/lib/docker/volumes/f17d91c72d0178c3746414175662884b29c462146c18fcf775c139a875dbd746/_data/mysql</span><br><span class="line">/<span class="keyword">var</span>/lib/docker/volumes/f8f07e5586d9f47cb5ec67a6b1fcd174c60446091e75ad0a920d58afefc8c405/_data/mysql</span><br><span class="line">/<span class="keyword">var</span>/lib/docker/overlay2/<span class="number">68559</span>b409701bd076a41a3a062d786093709ba872db563d90ce969222990e3ff/merged/etc/init.d/mysql</span><br><span class="line">/<span class="keyword">var</span>/lib/docker/overlay2/<span class="number">68559</span>b409701bd076a41a3a062d786093709ba872db563d90ce969222990e3ff/merged/etc/mysql</span><br><span class="line">/<span class="keyword">var</span>/lib/docker/overlay2/<span class="number">68559</span>b409701bd076a41a3a062d786093709ba872db563d90ce969222990e3ff/merged/<span class="keyword">var</span>/lib/mysql</span><br><span class="line">/<span class="keyword">var</span>/lib/docker/overlay2/<span class="number">68559</span>b409701bd076a41a3a062d786093709ba872db563d90ce969222990e3ff/merged/<span class="keyword">var</span>/log/mysql</span><br><span class="line">/<span class="keyword">var</span>/lib/docker/overlay2/<span class="number">68559</span>b409701bd076a41a3a062d786093709ba872db563d90ce969222990e3ff/merged/usr/bin/mysql</span><br><span class="line">/<span class="keyword">var</span>/lib/docker/overlay2/<span class="number">68559</span>b409701bd076a41a3a062d786093709ba872db563d90ce969222990e3ff/merged/usr/lib/mysql</span><br><span class="line">/<span class="keyword">var</span>/lib/docker/overlay2/<span class="number">68559</span>b409701bd076a41a3a062d786093709ba872db563d90ce969222990e3ff/merged/usr/share/mysql</span><br><span class="line"></span><br><span class="line">rm -rf /<span class="keyword">var</span>/lib/mysql</span><br><span class="line">rm -rf /etc/my.cnf</span><br><span class="line">rm -rf /<span class="keyword">var</span>/log/mysqld.log</span><br></pre></td></tr></table></figure>
<h3 id="安装mysql5-7"><a href="#安装mysql5-7" class="headerlink" title="安装mysql5.7"></a>安装mysql5.7</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br></pre></td><td class="code"><pre><span class="line">wget http:<span class="comment">//dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm</span></span><br><span class="line">yum localinstall mysql57-community-release-el7<span class="number">-8.</span>noarch.rpm</span><br><span class="line">yum repolist enabled | grep <span class="string">"mysql.*-community.*"</span></span><br><span class="line">mysql&gt; system yum repolist enabled | grep <span class="string">"mysql.*-community.*"</span></span><br><span class="line">Repository epel is listed more than once <span class="keyword">in</span> the configuration</span><br><span class="line">mysql-connectors-community/x86_64 MySQL Connectors Community                  <span class="number">74</span></span><br><span class="line">mysql-tools-community/x86_64      MySQL Tools Community                       <span class="number">74</span></span><br><span class="line">mysql57-community/x86_64          MySQL <span class="number">5.7</span> Community Server                 <span class="number">307</span></span><br><span class="line"> [root@VM_0_14_centos ~]# yum install mysql-community-server</span><br><span class="line"> grep <span class="string">'temporary password'</span> /<span class="keyword">var</span>/log/mysqld.log</span><br><span class="line"> Loaded plugins: fastestmirror, langpacks</span><br><span class="line"> Repository epel is listed more than once <span class="keyword">in</span> the configuration</span><br><span class="line"> Determining fastest mirrors</span><br><span class="line">  * nux-dextop: li.nux.ro</span><br><span class="line">  * webtatic: us-east.repo.webtatic.com</span><br><span class="line"> Package mysql-community-server<span class="number">-5.7</span><span class="number">.24</span><span class="number">-1.</span>el7.x86_64 already installed and latest version</span><br><span class="line"> Nothing to <span class="keyword">do</span></span><br><span class="line">     [root@VM_0_14_centos ~]# grep 'temporary password' /var/log/mysqld.log</span><br><span class="line">     [root@VM_0_14_centos ~]#</span><br><span class="line">     [root@VM_0_14_centos ~]# service mysqld restart</span><br><span class="line">     Redirecting to /bin/systemctl restart  mysqld.service</span><br><span class="line">     </span><br><span class="line">     [root@VM_0_14_centos ~]# /bin/systemctl restart  mysqld.service</span><br><span class="line">     [root@VM_0_14_centos ~]# ps aux|grep mysql</span><br><span class="line">     systemd+   <span class="number">765</span>  <span class="number">0.0</span>  <span class="number">0.2</span> <span class="number">1121296</span> <span class="number">4316</span> ?        Ssl   <span class="number">2018</span>  <span class="number">38</span>:<span class="number">00</span> mysqld</span><br><span class="line">     mysql    <span class="number">11499</span>  <span class="number">0.3</span>  <span class="number">8.8</span> <span class="number">1119512</span> <span class="number">166152</span> ?      Sl   <span class="number">17</span>:<span class="number">47</span>   <span class="number">0</span>:<span class="number">00</span> /usr/sbin/mysqld --daemonize --pid-file=<span class="regexp">/var/</span>run/mysqld/mysqld.pid</span><br><span class="line">     root     <span class="number">11769</span>  <span class="number">0.0</span>  <span class="number">0.0</span> <span class="number">112708</span>   <span class="number">964</span> pts/<span class="number">3</span>    R+   <span class="number">17</span>:<span class="number">49</span>   <span class="number">0</span>:<span class="number">00</span> grep --color=auto mysql</span><br><span class="line">     [root@VM_0_14_centos ~]# which mysqld</span><br><span class="line">     /usr/sbin/mysqld</span><br><span class="line">     [root@VM_0_14_centos ~]# lsof -i:3306</span><br><span class="line">     COMMAND   PID  USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME</span><br><span class="line">     mysqld  <span class="number">11499</span> mysql   <span class="number">18</span>u  IPv6 <span class="number">60264974</span>      <span class="number">0</span>t0  TCP *:mysql (LISTEN)</span><br><span class="line">     [root@VM_0_14_centos ~]# grep 'password' /var/log/mysqld.log</span><br><span class="line">     <span class="number">2019</span><span class="number">-01</span><span class="number">-14</span>T09:<span class="number">46</span>:<span class="number">16.712229</span>Z <span class="number">1</span> [Note] A temporary password is generated <span class="keyword">for</span> root@localhost: RpvpdgHKZ5;*</span><br><span class="line">     <span class="number">2019</span><span class="number">-01</span><span class="number">-14</span>T09:<span class="number">47</span>:<span class="number">39.920810</span>Z <span class="number">0</span> [Note] Shutting down plugin <span class="string">'validate_password'</span></span><br><span class="line">     <span class="number">2019</span><span class="number">-01</span><span class="number">-14</span>T09:<span class="number">47</span>:<span class="number">41.646659</span>Z <span class="number">0</span> [Note] Shutting down plugin <span class="string">'sha256_password'</span></span><br><span class="line">     <span class="number">2019</span><span class="number">-01</span><span class="number">-14</span>T09:<span class="number">47</span>:<span class="number">41.646662</span>Z <span class="number">0</span> [Note] Shutting down plugin <span class="string">'mysql_native_password'</span></span><br><span class="line">     [root@VM_0_14_centos ~]# mysql -uroot -p</span><br><span class="line">     Enter password:</span><br><span class="line">     Welcome to the MySQL monitor.  Commands end <span class="keyword">with</span> ; or \g.</span><br><span class="line">     Your MySQL connection id is <span class="number">2</span></span><br><span class="line">     Server version: <span class="number">5.7</span><span class="number">.24</span></span><br><span class="line">mysql&gt; use mysql</span><br><span class="line">ERROR <span class="number">1820</span> (HY000): You must reset your password using ALTER USER statement before executing <span class="keyword">this</span> statement.</span><br><span class="line">mysql&gt;  ALTER USER <span class="string">'root'</span>@<span class="string">'localhost'</span> IDENTIFIED BY <span class="string">'*SUsheng*'</span>;</span><br><span class="line">ERROR <span class="number">1819</span> (HY000): Your password does not satisfy the current policy requirements</span><br><span class="line">mysql&gt;  ALTER USER <span class="string">'root'</span>@<span class="string">'localhost'</span> IDENTIFIED BY <span class="string">'*SUsheng123*'</span>;</span><br><span class="line">Query OK, <span class="number">0</span> rows affected (<span class="number">0.00</span> sec)</span><br><span class="line">GRANT ALL PRIVILEGES ON *.* TO <span class="string">'root'</span>@<span class="string">'%'</span> IDENTIFIED BY <span class="string">'YourPassword9#'</span> WITH GRANT OPTION;</span><br><span class="line">修改/etc/my.cnf配置文件，在[mysqld]下添加编码配置</span><br><span class="line">vim /etc/my.cnf</span><br><span class="line">[mysqld]</span><br><span class="line">character_set_server=utf8</span><br><span class="line">init_connect=<span class="string">'SET NAMES utf8'</span></span><br><span class="line">λ mysql -h <span class="number">118.24</span><span class="number">.158</span><span class="number">.116</span> -uroot -p</span><br><span class="line">Enter password: ***********</span><br><span class="line">Welcome to the MySQL monitor.  Commands end <span class="keyword">with</span> ; or \g.</span><br><span class="line">Your MySQL connection id is <span class="number">3</span></span><br><span class="line">Server version: <span class="number">5.7</span><span class="number">.24</span> MySQL Community Server (GPL)</span><br><span class="line"></span><br><span class="line">mysql5<span class="number">.7</span> 以后的争强了安全机制,所以使用yum安装,启动会系统会自动生成一个随机的密码，并且不能设置简单密码。所以需要修改 mysql 全局参数</span><br><span class="line"></span><br><span class="line">先用日志密码登录 mysql </span><br><span class="line"></span><br><span class="line">grep <span class="string">'temporary password'</span> /<span class="keyword">var</span>/log/mysqld.log</span><br><span class="line"></span><br><span class="line">会输出结果: A temporary password is generated <span class="keyword">for</span> root@localhost: ******</span><br><span class="line"></span><br><span class="line">使用此密码登录后 执行 SHOW VARIABLES LIKE <span class="string">'validate_password%‘;  查看 mysql 密码策略</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">+--------------------------------------+--------+</span></span><br><span class="line"><span class="string">| Variable_name                        | Value  |</span></span><br><span class="line"><span class="string">+--------------------------------------+--------+</span></span><br><span class="line"><span class="string">| validate_password_check_user_name    | OFF    | </span></span><br><span class="line"><span class="string">| validate_password_dictionary_file    |        |</span></span><br><span class="line"><span class="string">| validate_password_length             | 8      |</span></span><br><span class="line"><span class="string">| validate_password_mixed_case_count   | 1      |</span></span><br><span class="line"><span class="string">| validate_password_number_count       | 1      |</span></span><br><span class="line"><span class="string">| validate_password_policy             | MEDIUM | </span></span><br><span class="line"><span class="string">| validate_password_special_char_count | 1      |</span></span><br><span class="line"><span class="string">+--------------------------------------+--------+</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">执行 set global validate_password_policy=LOW;  修改密码策略</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">执行 set global validate_password_length=6; 修改验证密码长度</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">切换 user 库</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">update user set authentication_string = password('</span>root<span class="string">'), password_expired = '</span>N<span class="string">', password_last_changed = now() where user = '</span>root<span class="string">';</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">重启 mysqld 服务，再用新密码登录即可</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">如果无法登录,提示Access denied for user '</span>root<span class="string">'@'</span>localhost<span class="string">'</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">重新更新 root 用户的 plugin 字段</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">update user set plugin='</span>mysql_native_password<span class="string">' where user = '</span>root<span class="string">';</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">更新成功后.重新执行更新密码操作</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">刷新权限  flush privileges;</span></span><br></pre></td></tr></table></figure>
<h3 id="查看实时执行的SQL语句"><a href="#查看实时执行的SQL语句" class="headerlink" title="查看实时执行的SQL语句"></a>查看实时执行的SQL语句</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SHOW VARIABLES LIKE <span class="string">"general_log%"</span>;</span><br><span class="line">如下general_log值为OFF说明没有开启：</span><br><span class="line"></span><br><span class="line">+------------------+----------------------------------+</span><br><span class="line">| Variable_name    | Value                            |</span><br><span class="line">+------------------+----------------------------------+</span><br><span class="line">| general_log      | OFF                              |</span><br><span class="line">| general_log_file | <span class="regexp">/var/</span>lib/mysql/galley-pc.log |</span><br><span class="line">+------------------+----------------------------------+</span><br><span class="line"><span class="number">2</span> rows <span class="keyword">in</span> set (<span class="number">0.00</span> sec)</span><br><span class="line">mysql&gt; SET GLOBAL general_log = <span class="string">'ON'</span>;</span><br><span class="line">mysql&gt; SET GLOBAL general_log_file = <span class="string">'/var/log/mysql/general_log.log'</span>;</span><br><span class="line">永久有效需要配置my.cnf文件，加入下面两行：</span><br><span class="line"></span><br><span class="line">general_log = <span class="number">1</span></span><br><span class="line">general_log_file = <span class="regexp">/var/</span>log/mysql/general_sql.log</span><br><span class="line">$ tail -f /<span class="keyword">var</span>/lib/mysql/general_sql.log</span><br><span class="line">/usr/sbin/mysqld, <span class="attr">Version</span>: <span class="number">5.7</span><span class="number">.24</span> (MySQL Community Server (GPL)). started <span class="keyword">with</span>:</span><br><span class="line">Tcp port: <span class="number">3306</span>  Unix socket: <span class="regexp">/var/</span>lib/mysql/mysql.sock</span><br><span class="line">Time                 Id Command    Argument</span><br><span class="line"><span class="number">2019</span><span class="number">-01</span><span class="number">-15</span>T08:<span class="number">45</span>:<span class="number">47.794791</span>Z       <span class="number">137</span> Query     SHOW VARIABLES LIKE <span class="string">'general%'</span></span><br><span class="line"></span><br><span class="line">直接使用 /etc/mysql/debian.cnf 文件中 [client] 节提供的用户名和密码</span><br><span class="line">mysql -u*** -p</span><br><span class="line">切换到 mysql 数据库</span><br><span class="line">use mysql;</span><br><span class="line">更新密码</span><br><span class="line">update user set authentication_string = password(<span class="string">'root'</span>), password_expired = <span class="string">'N'</span>, password_last_changed = now() where user = <span class="string">'root'</span>;</span><br><span class="line">刷新权限 flush privileges;</span><br><span class="line">重启 mysqld 服务，再用新密码登录即可</span><br><span class="line">如果无法登录,提示 Access denied <span class="keyword">for</span> user <span class="string">'root'</span>@<span class="string">'localhost'</span></span><br><span class="line">重新更新 root 用户的 plugin 字段</span><br><span class="line">update user set plugin=<span class="string">'mysql_native_password'</span> where user = <span class="string">'root'</span>;</span><br><span class="line">更新成功后.重新执行更新密码操作</span><br></pre></td></tr></table></figure>
<h3 id="Can’t-connect-to-local-MySQL-server"><a href="#Can’t-connect-to-local-MySQL-server" class="headerlink" title="Can’t connect to local MySQL server"></a>Can’t connect to local MySQL server</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">[root@localhost app]# mysql</span><br><span class="line">ERROR <span class="number">2002</span> (HY000): Can<span class="string">'t connect to local MySQL server through socket '</span>/<span class="keyword">var</span>/lib/mysql/mysql.sock<span class="string">' (2)</span></span><br><span class="line"><span class="string">[root@localhost app]# mysql -uroot -p</span></span><br><span class="line"><span class="string">Enter password: </span></span><br><span class="line"><span class="string">ERROR 2002 (HY000): Can'</span>t connect to local MySQL server through socket <span class="string">'/var/lib/mysql/mysql.sock'</span> (<span class="number">2</span>)</span><br><span class="line">查询自己的 mysql.sock文件</span><br><span class="line"></span><br><span class="line">发现自己的路径在 </span><br><span class="line"></span><br><span class="line">[root@localhost data]# find / -name mysql.sock</span><br><span class="line">/tmp/mysql.sock</span><br><span class="line">则在 my.cnf 中添加指定 mysql.sock文件</span><br><span class="line"></span><br><span class="line">[root@localhost data]# vim /etc/my.cnf</span><br><span class="line">[mysqld]</span><br><span class="line">socket=<span class="regexp">/tmp/my</span>sql.sock</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">fack!! 重启mysql服务问题依旧存在</span><br><span class="line"></span><br><span class="line">于是添加软连接</span><br><span class="line"></span><br><span class="line">[root@localhost data]# mkdir -pv /var/lib/mysql</span><br><span class="line">mkdir: 已创建目录 “/<span class="keyword">var</span>/lib/mysql”</span><br><span class="line">[root@localhost data]# ln -s /tmp/mysql.sock /var/lib/mysql/mysql.sock</span><br><span class="line">[root@localhost data]# mysql</span><br><span class="line">Welcome to the MySQL monitor.  Commands end <span class="keyword">with</span> ; or \g.</span><br><span class="line">Your MySQL connection id is <span class="number">1</span></span><br><span class="line">Server version: <span class="number">5.6</span><span class="number">.16</span> Source distribution</span><br><span class="line">Copyright (c) <span class="number">2000</span>, <span class="number">2011</span>, Oracle and/or its affiliates. All rights reserved.</span><br><span class="line">Oracle is a registered trademark <span class="keyword">of</span> Oracle Corporation and/or its</span><br><span class="line">affiliates. Other names may be trademarks <span class="keyword">of</span> their respective</span><br><span class="line">owners.</span><br><span class="line">Type <span class="string">'help;'</span> or <span class="string">'\h'</span> <span class="keyword">for</span> help. Type <span class="string">'\c'</span> to clear the current input statement.</span><br><span class="line">mysql&gt;</span><br></pre></td></tr></table></figure>
<h3 id="Access-denied-for-user-‘root‘-’localhost’"><a href="#Access-denied-for-user-‘root‘-’localhost’" class="headerlink" title="Access denied for user ‘root‘@’localhost’"></a>Access denied for user ‘root‘@’localhost’</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"># /etc/init.d/mysqld stop //停止mysql服务的运行</span><br><span class="line"># mysqld_safe --user=mysql --skip-grant-tables --skip-networking &amp; //跳过受权表访问</span><br><span class="line"># mysql -u root mysql //登录mysql</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">在mysql5<span class="number">.7</span>以下的版本如下：</span><br><span class="line">mysql&gt; UPDATE user SET Password=PASSWORD(<span class="string">'newpassword'</span>) where USER=<span class="string">'root'</span> and host=<span class="string">'127.0.0.1'</span> or host=<span class="string">'localhost'</span>;<span class="comment">//把空的用户密码都修改成非空的密码就行了。</span></span><br><span class="line"></span><br><span class="line">在mysql5<span class="number">.7</span>版本如下：</span><br><span class="line"></span><br><span class="line">update mysql.user set authentication_string=password(<span class="string">'newpassword'</span>) where user=<span class="string">'root'</span> and host=<span class="string">'127.0.0.1'</span> or host=<span class="string">'localhost'</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">mysql&gt; FLUSH PRIVILEGES;</span><br><span class="line">mysql&gt; quit # /etc/init.d/mysqld restart //离开并重启mysql</span><br><span class="line"># mysql -uroot -p</span><br><span class="line">Enter password: &lt;输入新设的密码newpassword&gt; </span><br><span class="line">Connection:             Localhost via UNIX socket</span><br><span class="line">Server characterset:    latin1</span><br><span class="line">Db     characterset:    latin1</span><br><span class="line">Client characterset:    utf8</span><br><span class="line">Conn.  characterset:    utf8</span><br><span class="line">UNIX socket:            /var/lib/mysql/mysql.sock</span><br><span class="line"></span><br><span class="line">[root@localhost ~]# ps aux|grep mysqld</span><br><span class="line">root     10913  0.0  0.0 106228  1396 ?        S    Jan19   0:00 /bin/sh /usr/bin/mysqld_safe --datadir=/data1/mysql --socket=/tmp/mysql.sock --pid-file=/var/run/mysqld/mysqld.pid --basedir=/usr --user=mysql</span><br><span class="line">mysql    11147 57.8  3.4 3502672 416152 ?      Sl   Jan19 1706:42 /usr/sbin/mysqld --basedir=/usr --datadir=/data1/mysql --plugin-dir=/usr/lib64/mysql/plugin --user=mysql --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/tmp/mysql.sock</span><br></pre></td></tr></table></figure>
<h3 id="Can’t-connect-to-MySQL-server-on-‘127-0-0-1’"><a href="#Can’t-connect-to-MySQL-server-on-‘127-0-0-1’" class="headerlink" title="Can’t connect to MySQL server on ‘127.0.0.1’"></a>Can’t connect to MySQL server on ‘127.0.0.1’</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">[root@localhost ~]# mysql -uroot -p -h 127.0.0.1</span><br><span class="line">Enter password:</span><br><span class="line">ERROR <span class="number">2003</span> (HY000): Can<span class="string">'t connect to MySQL server on '</span><span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span><span class="string">' (111)</span></span><br><span class="line"><span class="string">[root@localhost ~]# grep bind /etc/my.cnf</span></span><br><span class="line"><span class="string">bind-address=172.16.7.27</span></span><br><span class="line"><span class="string">[root@localhost ~]# mysql -uroot -p -h 172.16.7.27</span></span><br><span class="line"><span class="string">Enter password:</span></span><br><span class="line"><span class="string">Welcome to the MySQL monitor.  Commands end with ; or \g.</span></span><br><span class="line"><span class="string">Your MySQL connection id is 3979750</span></span><br><span class="line"><span class="string">Server version: 5.7.11 MySQL Community Server (GPL)</span></span><br><span class="line"><span class="string">Connection:             172.16.7.27 via TCP/IP#和通过socket链接不同</span></span><br></pre></td></tr></table></figure>
<h3 id="转换编码"><a href="#转换编码" class="headerlink" title="转换编码"></a>转换编码</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line">DIR=$1 # 转换编码文件目录https://tonydeng.github.io/2015/11/27/batch-conversion-file-encoding/</span><br><span class="line">FT=$2  # 需要转换的文件类型（扩展名）</span><br><span class="line">SE=$3  # 原始编码</span><br><span class="line">DE=$4  # 目标编码</span><br><span class="line"><span class="keyword">for</span> file <span class="keyword">in</span> <span class="string">`find $DIR -type f -name "*.$FT"`</span>; <span class="keyword">do</span></span><br><span class="line">	echo <span class="string">"conversion $file encoding $SE to $DE"</span></span><br><span class="line">    iconv -f $SE -t $DE <span class="string">"$file"</span> &gt; <span class="string">"$file"</span>.tmp</span><br><span class="line">    mv -f <span class="string">"$file"</span>.tmp <span class="string">"$file"</span></span><br><span class="line">done</span><br><span class="line"><span class="comment">//./batch_conversion_encoding.sh ~/sdk1 java GBK UTF8</span></span><br></pre></td></tr></table></figure>
<h3 id="安装-MySQL8-0-13"><a href="#安装-MySQL8-0-13" class="headerlink" title="安装 MySQL8.0.13"></a>安装 MySQL8.0.13</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">wget -c <span class="string">'https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.13-1.el7.x86_64.rpm-bundle.tar'</span></span><br><span class="line">解压</span><br><span class="line">tar xvf mysql<span class="number">-8.0</span><span class="number">.13</span><span class="number">-1.</span>el7.x86_64.rpm-bundle.tar</span><br><span class="line">安装</span><br><span class="line">yum install mysql-community-libs<span class="number">-8.0</span><span class="number">.13</span><span class="number">-1.</span>el7.x86_64.rpm</span><br><span class="line">yum install mysql-community-libs-compat<span class="number">-8.0</span><span class="number">.13</span><span class="number">-1.</span>el7.x86_64.rpm</span><br><span class="line">yum install mysql-community-client<span class="number">-8.0</span><span class="number">.13</span><span class="number">-1.</span>el7.x86_64.rpm</span><br><span class="line">yum install mysql-community-server<span class="number">-8.0</span><span class="number">.13</span><span class="number">-1.</span>el7.x86_64.rpm</span><br><span class="line">设置数据库https:<span class="comment">//laravel-china.org/articles/22686</span></span><br><span class="line">初次安装没进去，在/etc/my.cnf 中添加 skip-grant-tables, 使用mysql -uroot 直接进入数据库，</span><br><span class="line">修改root账号密码：</span><br><span class="line">alter user <span class="string">'root'</span>@<span class="string">'localhost'</span> identified by <span class="string">'**'</span>;</span><br><span class="line">mysql <span class="number">8.0</span>以后默认加密方式跟<span class="number">5.7</span>不一样 ：</span><br><span class="line">ALTER USER <span class="string">'root'</span>@<span class="string">'localhost'</span> IDENTIFIED BY <span class="string">'**'</span> PASSWORD EXPIRE NEVER; <span class="comment">//修改用户永不过期</span></span><br><span class="line">ALTER USER <span class="string">'root'</span>@<span class="string">'localhost'</span> IDENTIFIED WITH mysql_native_password BY <span class="string">'***'</span>;<span class="comment">//更新一下用户的密码加密方式，修改密码</span></span><br><span class="line">flush privileges; <span class="comment">//执行完刷新权限</span></span><br><span class="line"></span><br><span class="line">创建新用户</span><br><span class="line">CREATE USER smile@% IDENTIFIED BY <span class="string">'passowrd'</span>; <span class="comment">//# 创建账号密码</span></span><br><span class="line">GRANT ALL ON . TO smile@% WITH GRANT OPTION; <span class="comment">//授予远程登录权限（.远程访问所有数据）</span></span><br><span class="line">REVOKE all privileges ON databasename.tablename FROM <span class="string">'username'</span>@<span class="string">'host'</span>; <span class="comment">//删除某些数据权限</span></span><br><span class="line">flush privileges;<span class="comment">//刷新权限</span></span><br><span class="line"><span class="comment">//不常用的 --- 创建过期用户</span></span><br><span class="line">CREATE USER smile@% IDENTIFIED BY <span class="string">'***'</span> PASSWORD EXPIRE INTERVAL <span class="number">90</span> DAY;</span><br><span class="line"><span class="comment">//数据库搞定</span></span><br><span class="line">service mysqld start restart stop</span><br></pre></td></tr></table></figure>
<h3 id="查询指定数据库的所有表名称"><a href="#查询指定数据库的所有表名称" class="headerlink" title="查询指定数据库的所有表名称"></a>查询指定数据库的所有表名称</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">USE information_schema;</span><br><span class="line"></span><br><span class="line">SELECT TABLE_NAME,table_rows FROM TABLES WHERE TABLE_SCHEMA = <span class="string">'数据库名字'</span> ORDER BY table_rows DESC;</span><br><span class="line">查询指定库的数据大小，索引大小</span><br><span class="line">SELECT CONCAT(ROUND(SUM(DATA_LENGTH/<span class="number">1024</span>/<span class="number">1024</span>),<span class="number">2</span>),<span class="string">'MB'</span>) AS total_data_size, CONCAT(ROUND(SUM(index_length)/(<span class="number">1024</span>*<span class="number">1024</span>), <span class="number">2</span>), <span class="string">' MB'</span>) AS total_index_size FROM TABLES  WHERE table_schema  =  <span class="string">'数据库名字'</span>;</span><br></pre></td></tr></table></figure>
<h3 id="MySQL-分区表"><a href="#MySQL-分区表" class="headerlink" title="MySQL 分区表"></a>MySQL 分区表</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//https://learnku.com/articles/22947</span></span><br><span class="line">如果需要定时清理一张普通大表里的历史数据。</span><br><span class="line"></span><br><span class="line">可以使用一个或多个带 where 条件的 <span class="keyword">delete</span> 语句去删除（where条件是时间）。 如果表数据量较大，这对数据库的造成了很大压力。即使我们把这些旧数据删除了，但是底层的数据文件并没有变小。</span><br><span class="line"></span><br><span class="line">为什么没有变小？</span><br><span class="line">当删除数据 时，MYSQL 并不会立即回收表空间。被已删除数据的占据的存储空间，以及索引位会空在那里，等待新的数据来弥补这个空缺。</span><br><span class="line">强行回收： OPTIMIZE TABLE</span><br><span class="line">mysql&gt; SHOW PLUGINS \G;</span><br><span class="line"></span><br><span class="line">*************************** <span class="number">43.</span> row ***************************</span><br><span class="line">   Name: partition</span><br><span class="line"> Status: ACTIVE</span><br><span class="line">   Type: STORAGE ENGINE</span><br><span class="line">Library: NULL</span><br><span class="line">License: GPL</span><br><span class="line">CREATE TABLE hash_partition_test (</span><br><span class="line">    id INT,</span><br><span class="line">    pdate INT</span><br><span class="line">)</span><br><span class="line">PARTITION BY HASH(id)</span><br><span class="line">PARTITIONS <span class="number">4</span>;</span><br><span class="line">CREATE TABLE range_partition_test (</span><br><span class="line">    id INT,</span><br><span class="line">    pdate INT</span><br><span class="line">)</span><br><span class="line">PARTITION BY RANGE (pdate) (</span><br><span class="line">    PARTITION p1 VALUES LESS THAN ( <span class="number">201702</span> ),</span><br><span class="line">    PARTITION p2 VALUES LESS THAN ( <span class="number">201703</span> ),</span><br><span class="line">    PARTITION p3 VALUES LESS THAN ( <span class="number">201704</span> ),</span><br><span class="line">    PARTITION p4 VALUES LESS THAN (MAXVALUE)</span><br><span class="line">);</span><br><span class="line">mysql&gt; select * <span class="keyword">from</span> range_partition_test;</span><br><span class="line">+------+--------+</span><br><span class="line">| id   | pdate  |</span><br><span class="line">+------+--------+</span><br><span class="line">|    <span class="number">1</span> | <span class="number">201701</span> |</span><br><span class="line">|    <span class="number">2</span> | <span class="number">201702</span> |</span><br><span class="line">|    <span class="number">3</span> | <span class="number">201703</span> |</span><br><span class="line">|    <span class="number">4</span> | <span class="number">201704</span> |</span><br><span class="line">|    <span class="number">5</span> | <span class="number">201705</span> |</span><br><span class="line">+------+--------+</span><br><span class="line"></span><br><span class="line">mysql&gt; explain partitions select * <span class="keyword">from</span> range_partition_test where pdate between <span class="number">201702</span> and <span class="number">201703</span>;</span><br><span class="line">+----+-------------+----------------------+------------+------+---------------+------+---------+------+------+----------+-------------+</span><br><span class="line">| id | select_type | table                | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |</span><br><span class="line">+----+-------------+----------------------+------------+------+---------------+------+---------+------+------+----------+-------------+</span><br><span class="line">|  <span class="number">1</span> | SIMPLE      | range_partition_test | p2,p3      | ALL  | NULL          | NULL | NULL    | NULL |    <span class="number">2</span> |    <span class="number">50.00</span> | Using where |</span><br><span class="line">+----+-------------+----------------------+------------+------+---------------+------+---------+------+------+----------+-------------+</span><br></pre></td></tr></table></figure>
<h3 id="limit优化"><a href="#limit优化" class="headerlink" title="limit优化"></a>limit优化</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line">MySQL的 limit m,n 工作原理就是先读取符合where条件的前面m+n条记录，然后抛弃前m条，返回后面n条，所以m越大，偏移量越大，性能就越差。这也是大部分ORM框架生成的分页sql</span><br><span class="line"></span><br><span class="line">SELECT * FROM</span><br><span class="line"> t_tel_record t1</span><br><span class="line">INNER JOIN (</span><br><span class="line"> SELECT f_id</span><br><span class="line"> FROM t_tel_record</span><br><span class="line"> WHERE f_qiye_id = xxx</span><br><span class="line"> ORDER BY f_id DESC</span><br><span class="line"> LIMIT <span class="number">999900</span>, <span class="number">100</span></span><br><span class="line">) t2 ON t1.f_id = t2.f_id</span><br><span class="line"></span><br><span class="line">min_id = SELECT f_id</span><br><span class="line">FROM t_tel_record</span><br><span class="line">WHERE f_qiye_id = xxx</span><br><span class="line">ORDER BY f_id DESC</span><br><span class="line">LIMIT <span class="number">999900</span>, <span class="number">1</span></span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">SELECT * FROM</span><br><span class="line">  t_tel_record t1</span><br><span class="line">WHERE f_qiye_id = xxx</span><br><span class="line">AND f_id &lt; &#123;min_id&#125; + <span class="number">1</span></span><br><span class="line">ORDER BY f_id DESC</span><br><span class="line">LIMIT <span class="number">100</span></span><br><span class="line">第一页：（降序）</span><br><span class="line">SELECT * FROM t_tel_record t1</span><br><span class="line">WHERE f_qiye_id = xxx</span><br><span class="line">ORDER BY f_id DESC LIMIT <span class="number">100</span></span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">获取结果集最大最小id：一般是第一条和最后一条，或者 max_id=max(f_id), min_id=min(f_id)</span><br><span class="line">下一页（如果有）：</span><br><span class="line">SELECT * FROM t_tel_record t1</span><br><span class="line">WHERE f_qiye_id = xxx</span><br><span class="line">AND f_id &lt; &#123;min_id&#125;  -- min_id变量</span><br><span class="line">ORDER BY f_id DESC LIMIT <span class="number">100</span></span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">上一页（如果有）：</span><br><span class="line">SELECT * FROM t_tel_record t1</span><br><span class="line">WHERE f_qiye_id = xxx</span><br><span class="line">AND f_id &gt; &#123;max_id&#125;  -- max_id变量</span><br><span class="line">ORDER BY f_id DESC LIMIT <span class="number">100</span></span><br><span class="line">最后一页：（降序）</span><br><span class="line">SELECT * FROM (</span><br><span class="line">  SELECT * FROM t_tel_record t1</span><br><span class="line">  WHERE f_qiye_id = xxx</span><br><span class="line">  ORDER BY f_id ASC LIMIT <span class="number">100</span>) AS t</span><br><span class="line">ORDER BY f_id DESC</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">倒数第二页：(以此类推)</span><br><span class="line">SELECT * FROM (</span><br><span class="line">  SELECT * FROM t_tel_record t1</span><br><span class="line">  WHERE f_qiye_id = xxx</span><br><span class="line">  ORDER BY f_id ASC LIMIT <span class="number">100</span>, <span class="number">100</span>) AS t</span><br><span class="line">ORDER BY f_id DESC</span><br></pre></td></tr></table></figure>
<h3 id="insert"><a href="#insert" class="headerlink" title="insert"></a>insert</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">-- 将 oldUsers 表中的数据插入到 users 表</span><br><span class="line">INSERT INTO <span class="string">`users`</span>(<span class="string">`email`</span>, <span class="string">`name`</span>, <span class="string">`password`</span>) SELECT <span class="string">`email`</span>, <span class="string">`name`</span>, <span class="string">`password`</span> FROM <span class="string">`oldUsers`</span>;</span><br><span class="line"></span><br><span class="line">-- 将 users 表的数据复制到 usersCopy 表</span><br><span class="line">SELECT * INTO <span class="string">`usersCopy`</span> FROM <span class="string">`users`</span>;</span><br><span class="line"></span><br><span class="line">-- 创建新表 usersCopy 并将 users 复制过去</span><br><span class="line">CREATE TABLE <span class="string">`usersCopy`</span> AS SELECT * FROM <span class="string">`users`</span>;</span><br><span class="line">-- 查询 products 表中 price 与 number 的乘积并设为别名 total</span><br><span class="line">SELECT <span class="string">`price`</span> * <span class="string">`number`</span> AS <span class="string">`total`</span> FROM <span class="string">`products`</span>;</span><br><span class="line">-- 查询 users 表中的 name 列并将其用括号括起而且设置列别名为 newName</span><br><span class="line">SELECT Concat(<span class="string">'('</span>, <span class="string">`name`</span>, <span class="string">')'</span>) AS <span class="string">`newName`</span> FROM <span class="string">`users`</span>;</span><br></pre></td></tr></table></figure>
<h3 id="bindParam-和-bindValue"><a href="#bindParam-和-bindValue" class="headerlink" title="bindParam 和 bindValue"></a>bindParam 和 bindValue</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">bindParam 的作用是将变量的引用绑定到预编译的 SQL 语句中，当绑定的变量值改变时 SQL 语句随之改变。</span><br><span class="line"></span><br><span class="line">$statement = $pdo-&gt;prepare(<span class="string">"INSERT INTO `posts` (`id`, `title`, `author`) VALUES (:id, :title, :author)"</span>);</span><br><span class="line">$id = <span class="number">11</span>;</span><br><span class="line">$title = <span class="string">'new post'</span>;</span><br><span class="line">$author = <span class="string">'unknown'</span>;</span><br><span class="line">$statement-&gt;bindParam(<span class="string">':id'</span>, $id, <span class="attr">PDO</span>::PARAM_INT);</span><br><span class="line">$statement-&gt;bindParam(<span class="string">':title'</span>, $title, <span class="attr">PDO</span>::PARAM_STR);</span><br><span class="line">$statement-&gt;bindParam(<span class="string">':author'</span>, $author, <span class="attr">PDO</span>::PARAM_STR);</span><br><span class="line">$statement-&gt;execute();</span><br><span class="line">$id = <span class="number">12</span>;</span><br><span class="line">$title = <span class="string">'new post2'</span>;</span><br><span class="line">$author = <span class="string">'unknown2'</span>;</span><br><span class="line">$statement-&gt;execute();</span><br><span class="line"><span class="comment">// 执行代码后查询数据库显示如下</span></span><br><span class="line"><span class="comment">// +----+-----------+----------+</span></span><br><span class="line"><span class="comment">// | id | title     | author   |</span></span><br><span class="line"><span class="comment">// +----+-----------+----------+</span></span><br><span class="line"><span class="comment">// |  1 | new post  | unknown  |</span></span><br><span class="line"><span class="comment">// |  2 | new post2 | unknown2 |</span></span><br><span class="line"><span class="comment">// +----+-----------+----------+</span></span><br><span class="line">警告：由于 bindParam 是绑定的是变量的引用，所以在 foreach 中会出现意料之外的 BUG。示例如下：</span><br><span class="line"></span><br><span class="line">$data = [<span class="string">':title'</span> =&gt; <span class="string">'title'</span>, <span class="string">':author'</span> =&gt; <span class="string">'author'</span>];</span><br><span class="line">$statement = $pdo-&gt;prepare(<span class="string">"INSERT INTO `posts` (`title`, `author`) VALUES (:title, :author)"</span>);</span><br><span class="line">foreach ($data <span class="keyword">as</span> $key =&gt; $val) &#123;</span><br><span class="line">    $statement-&gt;bindParam($key, $val);</span><br><span class="line">&#125;</span><br><span class="line">$statement-&gt;execute();</span><br><span class="line"><span class="comment">// 执行代码后查询数据库显示如下</span></span><br><span class="line"><span class="comment">// +----+--------+--------+</span></span><br><span class="line"><span class="comment">// | id | title  | author |</span></span><br><span class="line"><span class="comment">// +----+--------+--------+</span></span><br><span class="line"><span class="comment">// |  1 | author | author |</span></span><br><span class="line"><span class="comment">// +----+--------+--------+</span></span><br><span class="line">当循环结束后 $val 的值即为数组中最后一个元素的值，而 bindParam 方法绑定的是引用而不是值，所以此时所有的占位符绑定的都是循环结束后的 $val 变量值，因此就有了这个结果。 解决这个问题我们可以用 bindValue 方法实现。</span><br><span class="line"></span><br><span class="line">bindValue 的作用是绑定值到预编译的 SQL 语句中，一经绑定 SQL 语句就固定不变。示例如下：</span><br><span class="line"></span><br><span class="line">$data = [<span class="string">':title'</span> =&gt; <span class="string">'title'</span>, <span class="string">':author'</span> =&gt; <span class="string">'author'</span>];</span><br><span class="line">$statement = $pdo-&gt;prepare(<span class="string">"INSERT INTO `posts` (`title`, `author`) VALUES (:title, :author)"</span>);</span><br><span class="line">foreach ($data <span class="keyword">as</span> $key =&gt; $val) &#123;</span><br><span class="line">    $statement-&gt;bindValue($key, $val);</span><br><span class="line">&#125;</span><br><span class="line">$statement-&gt;execute();</span><br><span class="line"><span class="comment">// 执行代码后查询数据库显示如下</span></span><br><span class="line"><span class="comment">// +----+--------+--------+</span></span><br><span class="line"><span class="comment">// | id | title  | author |</span></span><br><span class="line"><span class="comment">// +----+--------+--------+</span></span><br><span class="line"><span class="comment">// |  1 | title  | author |</span></span><br><span class="line"><span class="comment">// +----+--------+--------+</span></span><br><span class="line">这样就解决了这个问题，当然我们还可以在 foreach 中使用引用的方式解决这个问题，但是不推荐。示例如下：</span><br><span class="line"></span><br><span class="line">$data = [<span class="string">':title'</span> =&gt; <span class="string">'title'</span>, <span class="string">':author'</span> =&gt; <span class="string">'author'</span>];</span><br><span class="line">$statement = $pdo-&gt;prepare(<span class="string">"INSERT INTO `posts` (`title`, `author`) VALUES (:title, :author)"</span>);</span><br><span class="line">foreach ($data <span class="keyword">as</span> $key =&gt; &amp;$val) &#123;</span><br><span class="line">    $statement-&gt;bindParam($key, $val);</span><br><span class="line">&#125;</span><br><span class="line">$statement-&gt;execute();</span><br><span class="line"><span class="comment">// 执行代码后查询数据库显示如下</span></span><br><span class="line"><span class="comment">// +----+--------+--------+</span></span><br><span class="line"><span class="comment">// | id | title  | author |</span></span><br><span class="line"><span class="comment">// +----+--------+--------+</span></span><br><span class="line"><span class="comment">// |  1 | title  | author |</span></span><br><span class="line"><span class="comment">// +----+--------+--------+</span></span><br></pre></td></tr></table></figure>
<h3 id="行列转换"><a href="#行列转换" class="headerlink" title="行列转换"></a>行列转换</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">#准备示例数据</span><br><span class="line">create table tbl_name (ID int ,mSize varchar(<span class="number">100</span>));</span><br><span class="line">insert into tbl_name values (<span class="number">1</span>,<span class="string">'tiny,small,big'</span>);</span><br><span class="line">insert into tbl_name values (<span class="number">2</span>,<span class="string">'small,medium'</span>);</span><br><span class="line">insert into tbl_name values (<span class="number">3</span>,<span class="string">'tiny,big'</span>);</span><br><span class="line"></span><br><span class="line">#用于行列转换循环的自增表</span><br><span class="line">create table incre_table (AutoIncreID int);</span><br><span class="line">insert into incre_table values (<span class="number">1</span>);</span><br><span class="line">insert into incre_table values (<span class="number">2</span>);</span><br><span class="line">insert into incre_table values (<span class="number">3</span>);</span><br><span class="line"> </span><br><span class="line"></span><br><span class="line">#实现行列转换的SQLhttp://cenalulu.github.io/mysql/column-row-reverse/</span><br><span class="line">select a.ID,substring_index(substring_index(a.mSize,<span class="string">','</span>,b.AutoIncreID),<span class="string">','</span>,<span class="number">-1</span>) </span><br><span class="line"><span class="keyword">from</span> </span><br><span class="line">tbl_name a</span><br><span class="line">join</span><br><span class="line">incre_table b</span><br><span class="line">on b.AutoIncreID &lt;= (length(a.mSize) - length(replace(a.mSize,<span class="string">','</span>,<span class="string">''</span>))+<span class="number">1</span>)</span><br><span class="line">order by a.ID;</span><br><span class="line">select a.ID,substring_index(substring_index(a.mSize,<span class="string">','</span>,b.help_topic_id+<span class="number">1</span>),<span class="string">','</span>,<span class="number">-1</span>) </span><br><span class="line"><span class="keyword">from</span> </span><br><span class="line">tbl_name a</span><br><span class="line">join</span><br><span class="line">mysql.help_topic b</span><br><span class="line">on b.help_topic_id &lt; (length(a.mSize) - length(replace(a.mSize,<span class="string">','</span>,<span class="string">''</span>))+<span class="number">1</span>)</span><br><span class="line">order by a.ID;</span><br></pre></td></tr></table></figure>
<h3 id="MySQL密码"><a href="#MySQL密码" class="headerlink" title="MySQL密码"></a>MySQL密码</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select password(<span class="string">'root'</span>),concat(<span class="string">'*'</span>,sha1(unhex(sha1(<span class="string">'root'</span>))));</span><br><span class="line">+-------------------------------------------+-------------------------------------------+</span><br><span class="line">| password(<span class="string">'root'</span>)                          | concat(<span class="string">'*'</span>,sha1(unhex(sha1(<span class="string">'root'</span>))))     |</span><br><span class="line">+-------------------------------------------+-------------------------------------------+</span><br><span class="line">| *<span class="number">81</span>F5E21E35407D884A6CD4A731AEBFB6AF209E1B | *<span class="number">81</span>f5e21e35407d884a6cd4a731aebfb6af209e1b |</span><br><span class="line">+-------------------------------------------+-------------------------------------------+</span><br><span class="line"><span class="number">5.6</span>以前如果你向MySQL发送了例如create user,grant user ... identified by这样的携带初始明文密码的指令，那么会在binary log中原原本本的被还原出来。</span><br><span class="line">mysql [localhost] &#123;msandbox&#125; (mysql) &gt; create user plain_password identified by <span class="string">'plain_pass'</span>;</span><br><span class="line">Query OK, <span class="number">0</span> rows affected (<span class="number">0.00</span> sec)</span><br><span class="line">用mysqlbinlog查看二进制日志 http:<span class="comment">//cenalulu.github.io/mysql/myall-about-mysql-password/</span></span><br><span class="line"></span><br><span class="line">shell&gt; mysqlbinlog binlog<span class="number">.000001</span></span><br><span class="line"># at 106</span><br><span class="line">#150227 23:37:59 server id 1  end_log_pos 223   Query   thread_id=1 exec_time=0 error_code=0</span><br><span class="line">use mysql<span class="comment">/*!*/</span>;</span><br><span class="line">SET TIMESTAMP=<span class="number">1425051479</span><span class="comment">/*!*/</span>;</span><br><span class="line">SET @@session.pseudo_thread_id=<span class="number">1</span><span class="comment">/*!*/</span>;</span><br><span class="line"></span><br><span class="line">change master to master_password=<span class="string">''</span>命令不在这个范畴中。这也就意味着MySQL5<span class="number">.6</span>中仍然使用这样的语法来启动replication时有安全风险的。这也就是为什么<span class="number">5.6</span>中使用带有明文密码的change master to时会有warning提示，具体如下：</span><br><span class="line"></span><br><span class="line">slave1 [localhost] &#123;msandbox&#125; ((none)) &gt; change master to master_host=<span class="string">'127.0.0.1'</span>,master_port =<span class="number">21288</span>,master_user=<span class="string">'rsandbox'</span>,master_password=<span class="string">'rsandbox'</span>,master_auto_position=<span class="number">1</span>;</span><br><span class="line">Query OK, <span class="number">0</span> rows affected, <span class="number">2</span> warnings (<span class="number">0.04</span> sec)</span><br><span class="line"></span><br><span class="line">slave1 [localhost] &#123;msandbox&#125; ((none)) &gt; show warnings;</span><br><span class="line">+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+</span><br><span class="line">| Level | Code | Message                                                                                                                                                                                                                                                                              |</span><br><span class="line">+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+</span><br><span class="line">| Note  | <span class="number">1759</span> | Sending passwords <span class="keyword">in</span> plain text without SSL/TLS is extremely insecure.                                                                                                                                                                                                               |</span><br><span class="line">| Note  | <span class="number">1760</span> | Storing MySQL user name or password information <span class="keyword">in</span> the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options <span class="keyword">for</span> START SLAVE; see the <span class="string">'START SLAVE Syntax'</span> <span class="keyword">in</span> the MySQL Manual <span class="keyword">for</span> more information. |</span><br><span class="line">+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+</span><br><span class="line"><span class="number">2</span> rows <span class="keyword">in</span> set (<span class="number">0.00</span> sec)</span><br></pre></td></tr></table></figure>
<h3 id="导出表数据"><a href="#导出表数据" class="headerlink" title="导出表数据"></a>导出表数据</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">select * <span class="keyword">from</span> table into outfile <span class="string">"/home/root/example.sql"</span> where +条件</span><br><span class="line">导入数据库</span><br><span class="line"></span><br><span class="line">$ mysqldump -uroot -p --<span class="keyword">default</span>-character-set=utf8 dbname tablename &gt;  <span class="regexp">/home/</span>root/example.sql</span><br><span class="line">转载数据</span><br><span class="line"></span><br><span class="line">load data local infile <span class="string">"/home/table.txt"</span> into table <span class="string">`table`</span>;</span><br></pre></td></tr></table></figure>
<h3 id="从数据库中获取随机的数据"><a href="#从数据库中获取随机的数据" class="headerlink" title="从数据库中获取随机的数据"></a>从数据库中获取随机的数据</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">User::inRandomOrder()-&gt;get();</span><br><span class="line">User::inRandomOrder()-&gt;first();</span><br><span class="line">User::orderByRaw(<span class="string">"RAND()"</span>)-&gt;get();</span><br><span class="line">use Illuminate\Database\Query\Builder;</span><br><span class="line"><span class="comment">//https://learnku.com/laravel/wikis/16199</span></span><br><span class="line">Builder::macro(<span class="string">'orderByRandom'</span>, <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"></span><br><span class="line">    $randomFunctions = [</span><br><span class="line">        <span class="string">'mysql'</span>  =&gt; <span class="string">'RAND()'</span>,</span><br><span class="line">        <span class="string">'pgsql'</span>  =&gt; <span class="string">'RANDOM()'</span>,</span><br><span class="line">        <span class="string">'sqlite'</span> =&gt; <span class="string">'RANDOM()'</span>,</span><br><span class="line">        <span class="string">'sqlsrv'</span> =&gt; <span class="string">'NEWID()'</span>,</span><br><span class="line">    ];</span><br><span class="line"></span><br><span class="line">    $driver = $<span class="keyword">this</span>-&gt;getConnection()-&gt;getDriverName();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> $<span class="keyword">this</span>-&gt;orderByRaw($randomFunctions[$driver]);</span><br><span class="line">&#125;);</span><br><span class="line">SELECT </span><br><span class="line">FROM table AS t1 JOIN (SELECT ROUND(RAND() ((SELECT MAX(id) FROM table)-(SELECT MIN(id) FROM table))+(SELECT MIN(id) FROM table)) AS id) AS t2</span><br><span class="line">WHERE t1.id &gt;= t2.id</span><br><span class="line">ORDER BY t1.id LIMIT <span class="number">1</span>;</span><br><span class="line">以前用过的，效率不错。</span><br></pre></td></tr></table></figure>
<h3 id="mysql5-7-datetime-默认值为‘0000-00-00-00-00-00’值无法创建问题解决"><a href="#mysql5-7-datetime-默认值为‘0000-00-00-00-00-00’值无法创建问题解决" class="headerlink" title="mysql5.7 datetime 默认值为‘0000-00-00 00:00:00’值无法创建问题解决"></a>mysql5.7 datetime 默认值为‘0000-00-00 00:00:00’值无法创建问题解决</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span>、使用root登陆数据库 命令界面执行</span><br><span class="line"></span><br><span class="line">select @@sql_mode;</span><br><span class="line"> 结果中包含下面两个</span><br><span class="line"></span><br><span class="line">NO_ZERO_IN_DATE,NO_ZERO_DATE</span><br><span class="line"><span class="number">2</span>、修改/etc/my.cnf，查找sql_model如果找不到则添加如下代码 </span><br><span class="line"></span><br><span class="line">sql_mode=<span class="string">"ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"</span></span><br><span class="line"><span class="number">3</span>、重启mysql</span><br><span class="line"></span><br><span class="line">/etc/ini.d/mysql restart</span><br><span class="line">简单几步大功告成！</span><br><span class="line"></span><br><span class="line"> http:<span class="comment">//118.25.60.91:9080/article/15 https://learnku.com/articles/16807</span></span><br><span class="line"></span><br><span class="line">原因：</span><br><span class="line"></span><br><span class="line">NO_ZERO_IN_DATE,NO_ZERO_DATE是无法默认为‘<span class="number">0000</span><span class="number">-00</span><span class="number">-00</span> <span class="number">00</span>:<span class="number">00</span>:<span class="number">00</span>’的根源。</span><br><span class="line"></span><br><span class="line">NO_ZERO_IN_DATE：在严格模式下，不允许日期和月份为零 </span><br><span class="line"></span><br><span class="line">NO_ZERO_DATE：设置该值，mysql数据库不允许插入零日期，插入零日期会抛出错误而不是警告。</span><br></pre></td></tr></table></figure>
<h3 id="Redis-分布式锁"><a href="#Redis-分布式锁" class="headerlink" title="Redis 分布式锁"></a>Redis 分布式锁</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * redis 加锁 --单Redis实例实现分布式锁</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * -- 分布式请使用：Redlock:https://github.com/ronnylt/redlock-php</span></span><br><span class="line"><span class="comment"> * -- 详情参考： http://www.redis.cn/topics/distlock.html</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * @package app\common\service</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">RedisLock</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">const</span> LOCK_SUCCESS = <span class="string">'OK'</span>;</span><br><span class="line">    <span class="keyword">const</span> IF_NOT_EXISTS = <span class="string">'NX'</span>;</span><br><span class="line">    <span class="keyword">const</span> MILLISECOND_EXPIRE_TIME = <span class="string">'PX'</span>;</span><br><span class="line">    <span class="keyword">const</span> EXPIRE_TIME = <span class="number">60000</span>; <span class="comment">// millisecond =&gt; 60s</span></span><br><span class="line">    <span class="keyword">const</span> LOCK_VALUE = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 加锁https://learnku.com/articles/15825/redis-distributed-lock-solution</span></span><br><span class="line"><span class="comment">         * @param $redis object</span></span><br><span class="line"><span class="comment">         * @param $key</span></span><br><span class="line"><span class="comment">         * @param string $expire_time 60000</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        public <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">lock</span>(<span class="params">$redis, $key, $expire_time=<span class="string">''</span></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">if</span> (empty($expire_time)) &#123;</span><br><span class="line">                    $expire_time = self::EXPIRE_TIME;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            $result = $redis-&gt;set($key, <span class="attr">self</span>::LOCK_VALUE, [self::IF_NOT_EXISTS, <span class="attr">self</span>::<span class="function"><span class="params">MILLISECOND_EXPIRE_TIME</span> =&gt;</span> $expire_time]);</span><br><span class="line"></span><br><span class="line">            <span class="keyword">return</span> self::LOCK_SUCCESS === (string)$result;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 解锁https://github.com/laravel/framework/blob/5.6/src/Illuminate/Cache/RedisLock.php#L36 </span></span><br><span class="line"><span class="comment">         *</span></span><br><span class="line"><span class="comment">         * 参考： https://github.com/phpredis/phpredis/blob/develop/tests/RedisTest.php</span></span><br><span class="line"><span class="comment">         * @param $redis</span></span><br><span class="line"><span class="comment">         * @param $key</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        public <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">unlock</span>(<span class="params">$redis, $key</span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            $lua =&lt;&lt;&lt;EOT</span><br><span class="line">if redis.call("get",KEYS[1]) == ARGV[1] then</span><br><span class="line">    return redis.call("del",KEYS[1])</span><br><span class="line">else</span><br><span class="line">    return 0</span><br><span class="line">end</span><br><span class="line">EOT;</span><br><span class="line">            $result = $redis-&gt;eval($lua, array($key, self::LOCK_VALUE), 1);</span><br><span class="line">            return $result;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">public function acquire()</span><br><span class="line">    &#123;</span><br><span class="line">        $result = $this-&gt;redis-&gt;setnx($this-&gt;name, 1);</span><br><span class="line">        if ($result === 1 &amp;&amp; $this-&gt;seconds &gt; 0) &#123;</span><br><span class="line">            $this-&gt;redis-&gt;expire($this-&gt;name, $this-&gt;seconds);</span><br><span class="line">        &#125;</span><br><span class="line">        return $result === 1;</span><br><span class="line">    &#125;</span><br><span class="line">    /**</span><br><span class="line">     * Release the lock.</span><br><span class="line">     *</span><br><span class="line">     * @return void</span><br><span class="line">     */</span><br><span class="line">    public function release()</span><br><span class="line">    &#123;</span><br><span class="line">        $this-&gt;redis-&gt;del($this-&gt;name);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<h3 id="redis-cli"><a href="#redis-cli" class="headerlink" title="redis-cli"></a>redis-cli</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//https://juejin.im/book/5afc2e5f6fb9a07a9b362527/section/5bcfd27051882577e962f064</span></span><br><span class="line">$ redis-cli incrby foo <span class="number">5</span></span><br><span class="line">(integer) <span class="number">5</span></span><br><span class="line">$ redis-cli incrby foo <span class="number">5</span></span><br><span class="line">(integer) <span class="number">10</span></span><br><span class="line">$ redis-cli info &gt; info.txt</span><br><span class="line">$ wc -l info.txt</span><br><span class="line">     <span class="number">120</span> info.txt</span><br><span class="line"><span class="comment">// -n 2 表示使用第2个库，相当于 select 2</span></span><br><span class="line">$ redis-cli -h localhost -p <span class="number">6379</span> -n <span class="number">2</span> ping</span><br><span class="line">PONG</span><br><span class="line">$ cat cmds.txt</span><br><span class="line">set foo1 bar1</span><br><span class="line">set foo2 bar2</span><br><span class="line">set foo3 bar3</span><br><span class="line">......</span><br><span class="line">$ cat cmds.txt | redis-cli</span><br><span class="line">OK</span><br><span class="line">OK</span><br><span class="line">OK</span><br><span class="line">$ redis-cli &lt; cmds.txt</span><br><span class="line">OK</span><br><span class="line">OK</span><br><span class="line">OK</span><br><span class="line"><span class="comment">// 间隔1s，执行5次，观察qps的变化</span></span><br><span class="line">$ redis-cli -r <span class="number">5</span> -i <span class="number">1</span> info | grep ops</span><br><span class="line">instantaneous_ops_per_sec:<span class="number">43469</span></span><br><span class="line">instantaneous_ops_per_sec:<span class="number">47460</span></span><br><span class="line">如果将次数设置为 <span class="number">-1</span> 那就是重复无数次永远执行下去。如果不提供 -i 参数，那就没有间隔，连续重复执行。在交互模式下也可以重复执行指令，形式上比较怪异，在指令前面增加次数</span><br><span class="line"></span><br><span class="line"><span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>:<span class="number">6379</span>&gt; <span class="number">5</span> ping</span><br><span class="line">PONG</span><br><span class="line">PONG</span><br><span class="line">PONG</span><br><span class="line">PONG</span><br><span class="line">PONG</span><br><span class="line"># 下面的指令很可怕，你的屏幕要愤怒了</span><br><span class="line"><span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>:<span class="number">6379</span>&gt; <span class="number">10000</span> info</span><br><span class="line">$ redis-cli rpush lfoo a b c d e f g</span><br><span class="line">(integer) <span class="number">7</span></span><br><span class="line">$ redis-cli --csv lrange lfoo <span class="number">0</span> <span class="number">-1</span></span><br><span class="line"><span class="string">"a"</span>,<span class="string">"b"</span>,<span class="string">"c"</span>,<span class="string">"d"</span>,<span class="string">"e"</span>,<span class="string">"f"</span>,<span class="string">"g"</span></span><br><span class="line">$ redis-cli hmset hfoo a <span class="number">1</span> b <span class="number">2</span> c <span class="number">3</span> d <span class="number">4</span></span><br><span class="line">OK</span><br><span class="line">$ redis-cli --csv hgetall hfoo</span><br><span class="line"><span class="string">"a"</span>,<span class="string">"1"</span>,<span class="string">"b"</span>,<span class="string">"2"</span>,<span class="string">"c"</span>,<span class="string">"3"</span>,<span class="string">"d"</span>,<span class="string">"4"</span></span><br><span class="line">$ redis-cli --csv -r <span class="number">5</span> hgetall hfoo</span><br><span class="line"><span class="string">"a"</span>,<span class="string">"1"</span>,<span class="string">"b"</span>,<span class="string">"2"</span>,<span class="string">"c"</span>,<span class="string">"3"</span>,<span class="string">"d"</span>,<span class="string">"4"</span></span><br><span class="line"><span class="string">"a"</span>,<span class="string">"1"</span>,<span class="string">"b"</span>,<span class="string">"2"</span>,<span class="string">"c"</span>,<span class="string">"3"</span>,<span class="string">"d"</span>,<span class="string">"4"</span></span><br><span class="line"><span class="string">"a"</span>,<span class="string">"1"</span>,<span class="string">"b"</span>,<span class="string">"2"</span>,<span class="string">"c"</span>,<span class="string">"3"</span>,<span class="string">"d"</span>,<span class="string">"4"</span></span><br><span class="line"><span class="string">"a"</span>,<span class="string">"1"</span>,<span class="string">"b"</span>,<span class="string">"2"</span>,<span class="string">"c"</span>,<span class="string">"3"</span>,<span class="string">"d"</span>,<span class="string">"4"</span></span><br><span class="line"><span class="string">"a"</span>,<span class="string">"1"</span>,<span class="string">"b"</span>,<span class="string">"2"</span>,<span class="string">"c"</span>,<span class="string">"3"</span>,<span class="string">"d"</span>,<span class="string">"4"</span></span><br><span class="line"><span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>:<span class="number">6379</span>&gt; <span class="built_in">eval</span> <span class="string">"return redis.pcall('mset', KEYS[1], ARGV[1], KEYS[2], ARGV[2])"</span> <span class="number">2</span> foo1 foo2 bar1 bar2</span><br><span class="line">OK</span><br><span class="line"><span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>:<span class="number">6379</span>&gt; <span class="built_in">eval</span> <span class="string">"return redis.pcall('mget', KEYS[1], KEYS[2])"</span> <span class="number">2</span> foo1 foo2</span><br><span class="line"><span class="number">1</span>) <span class="string">"bar1"</span></span><br><span class="line"><span class="number">2</span>) <span class="string">"bar2"</span></span><br><span class="line">redis-cli --stat 参数来实时监控服务器的状态，间隔 <span class="number">1</span>s 实时输出一次。</span><br><span class="line">$ ./redis-cli --bigkeys -i <span class="number">0.01</span></span><br><span class="line">--bigkeys 参数可以很快扫出内存里的大 KEY，使用 -i 参数控制扫描间隔，避免扫描指令导致服务器的 ops 陡增报警。</span><br><span class="line">$ redis-cli --host <span class="number">192.168</span>.x.x --port <span class="number">6379</span> monitor</span><br><span class="line"><span class="number">1539853410.458483</span> [<span class="number">0</span> <span class="number">10.100</span><span class="number">.90</span><span class="number">.62</span>:<span class="number">34365</span>] <span class="string">"GET"</span> <span class="string">"6yax3eb6etq8:&#123;-7&#125;"</span></span><br><span class="line"><span class="number">1539853410.459212</span> [<span class="number">0</span> <span class="number">10.100</span><span class="number">.90</span><span class="number">.61</span>:<span class="number">56659</span>] <span class="string">"PFADD"</span> <span class="string">"growth:dau:20181018"</span> <span class="string">"2klxkimass8w"</span></span><br><span class="line">如果你想观察主从服务器之间都同步了那些数据，可以使用 redis-cli 模拟从库。</span><br><span class="line"></span><br><span class="line">$ ./redis-cli --host <span class="number">192.168</span>.x.x --port <span class="number">6379</span> --slave</span><br><span class="line">SYNC <span class="keyword">with</span> master, discarding <span class="number">51778306</span> bytes <span class="keyword">of</span> bulk transfer...</span><br><span class="line">$ ./redis-cli --host <span class="number">192.168</span>.x.x --port <span class="number">6379</span> --rdb ./user.rdb</span><br><span class="line">SYNC sent to master, writing <span class="number">2501265095</span> bytes to <span class="string">'./user.rdb'</span> 远程 rdb 备份</span><br><span class="line"></span><br><span class="line">只有query执行时间大于slowlog-log-slower-than的才会定义成慢查询，才会被slowlog进行记录。slowlog-log-slower-than设置的单位是微秒，默认是<span class="number">10000</span>微秒，也就是<span class="number">10</span>毫秒。slowlog-max-len表示慢查询最大的条数，当slowlog超过设定的最大值后，会将最早的slowlog删除，是个FIFO队列。</span><br><span class="line"></span><br><span class="line">查看slowlog总条数</span><br><span class="line"></span><br><span class="line"><span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>:<span class="number">6379</span>&gt; SLOWLOG LEN</span><br><span class="line"></span><br><span class="line">(integer) <span class="number">4</span></span><br><span class="line"><span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>:<span class="number">6379</span>&gt; CONFIG GET slowlog-*</span><br><span class="line"><span class="number">1</span>) <span class="string">"slowlog-log-slower-than"</span></span><br><span class="line"><span class="number">2</span>) <span class="string">"100"</span></span><br><span class="line"><span class="number">3</span>) <span class="string">"slowlog-max-len"</span></span><br><span class="line"><span class="number">4</span>) <span class="string">"1024"</span></span><br><span class="line"><span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>:<span class="number">6379</span>&gt; SLOWLOG GET <span class="number">11</span>) <span class="number">1</span>) (integer) <span class="number">26</span>            <span class="comment">// slowlog唯一编号id2) (integer) 1440057815    // 查询的时间戳3) (integer) 47            // 查询的耗时（微秒），如表示本条命令查询耗时47微秒4) 1) "SLOWLOG"            // 查询命令，完整命令为 SLOWLOG GET，slowlog最多保存前面的31个key和128字符2) "GET"</span></span><br><span class="line"></span><br><span class="line"> debug sleep阻塞了set命令，set命令的整体响应时间(R)是<span class="number">1530357</span>微秒，而其服务时间(S)为<span class="number">8</span>微秒，排队延迟(Q)为<span class="number">1530349</span>微秒。</span><br><span class="line"> </span><br><span class="line"> Session<span class="number">-1</span>:</span><br><span class="line"> xxxx:<span class="number">6386</span>&gt; debug sleep <span class="number">6</span></span><br><span class="line"> OK</span><br><span class="line"> (<span class="number">6.00</span>s)</span><br><span class="line"> </span><br><span class="line"> Session<span class="number">-2</span>:</span><br><span class="line"> xxxxx:<span class="number">6386</span>&gt; set a b</span><br><span class="line"> OK</span><br><span class="line"> (<span class="number">1.53</span>s)</span><br><span class="line"> <span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>:<span class="number">6379</span>&gt; SLOWLOG RESET</span><br><span class="line"> OK</span><br><span class="line"> <span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>:<span class="number">6379</span>&gt; SLOWLOG LEN</span><br><span class="line"> (integer) <span class="number">0</span></span><br><span class="line"> redis-cli monitor打印出所有sever接收到的命令以及其对应的客户端地址</span><br><span class="line"> </span><br><span class="line"> $ redis-cli monitor</span><br><span class="line"> redis-cli --stat查看当前连接的客户端数，连接数等</span><br><span class="line"> 按前缀/模式批量删除keys</span><br><span class="line"> redis-cli keys david* | xargs redis-cli del</span><br><span class="line"> <span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>:<span class="number">6379</span>&gt; <span class="built_in">eval</span> <span class="string">"local keys = redis.call('keys',KEYS[1]) for i,v in ipairs(keys) do redis.call('del',v) end"</span> <span class="number">1</span> david*</span><br></pre></td></tr></table></figure>
<h3 id="每个分组的最后一条记录"><a href="#每个分组的最后一条记录" class="headerlink" title="每个分组的最后一条记录"></a>每个分组的最后一条记录</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">select * <span class="keyword">from</span> t_tmp group by FCityId order by FUpdateTime desc;<span class="string">` 结果却是错误的！http://blog.text.wiki/2015/04/03/retrieve-the-last-record-in-each-group.html</span></span><br><span class="line"><span class="string">SELECT * FROM (SELECT * FROM t_tmp ORDER BY FUpdateTime DESC)tmptable GROUP BY FCityId ORDER BY FUpdateTime DESC;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">SELECT m1. * FROM t_tmp m1 LEFT JOIN t_tmp m2 ON ( m1.FCityId = m2.FCity</span></span><br><span class="line"><span class="string">Id AND m1.FId &lt; m2.FId )  WHERE m2.FId IS NULL ORDER BY FUpdateTime DESC LIMIT 0</span></span><br><span class="line"><span class="string">, 30;</span></span><br></pre></td></tr></table></figure>
<h3 id="超过经理收入的员工"><a href="#超过经理收入的员工" class="headerlink" title="超过经理收入的员工"></a>超过经理收入的员工</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"> SELECT e.Name AS Employee</span><br><span class="line">    FROM Employee e, Employee e1</span><br><span class="line">    WHERE e.ManagerId = e1.id</span><br><span class="line">        AND e.Salary &gt; e1.Salary;</span><br><span class="line">Department	Employee	Salary</span><br><span class="line">IT	Max	<span class="number">90000</span></span><br><span class="line">Sales	Henry	<span class="number">80000</span></span><br><span class="line">https:<span class="comment">//learnku.com/articles/24492</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL-之事务隔离级别"><a href="#MySQL-之事务隔离级别" class="headerlink" title="MySQL 之事务隔离级别"></a>MySQL 之事务隔离级别</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line">MySQL事务主要用于处理一个包含操作量比较大、复杂的业务。比如说，删除一个学生，我们除了要删除该学生的基本信息，同时也要删除考试记录、违规记录等。诸多的操作组成一个事务。事务是用来管理insert、update、<span class="keyword">delete</span>基本指令的。当MySQL使用innodb引擎的前提下才支持事务操作</span><br><span class="line">https:<span class="comment">//learnku.com/articles/24581#topnav https://www.itcodemonkey.com/article/13020.html</span></span><br><span class="line">隔离性的类别</span><br><span class="line"></span><br><span class="line">read uncommitted | 读未提交</span><br><span class="line">read committed | 读已提交</span><br><span class="line">repeatable read | 可重复读</span><br><span class="line">serializable | 串行化</span><br><span class="line">在MySQL数据库中，引擎默认使用repeatable read</span><br><span class="line"></span><br><span class="line"># SELECT @@tx_isolation 或者 SELECT @@transaction_isolation</span><br><span class="line"># MySQL 8.x </span><br><span class="line"># transaction_isolation在MySQL 5.7.20中添加了作为别名 tx_isolation，现已弃用，并在MySQL 8.0中删除。</span><br><span class="line"># 应调整应用程序transaction_isolation以优先使用 tx_isolation。</span><br><span class="line">mysql&gt; SELECT @@transaction_isolation;</span><br><span class="line">+-------------------------+</span><br><span class="line">| @@transaction_isolation |</span><br><span class="line">+-------------------------+</span><br><span class="line">| REPEATABLE-READ         |</span><br><span class="line">+-------------------------+</span><br><span class="line"><span class="number">1</span> row <span class="keyword">in</span> set (<span class="number">0.01</span> sec)</span><br><span class="line"></span><br><span class="line">## 将事务隔离的模式设置为[可重复读]</span><br><span class="line">mysql&gt; set session transaction isolation level repeatable read;</span><br><span class="line">Query OK, <span class="number">0</span> rows affected (<span class="number">0.00</span> sec)</span><br><span class="line"></span><br><span class="line">## (1)事务A读取scor数据表</span><br><span class="line">mysql&gt; select * <span class="keyword">from</span> score;</span><br><span class="line">+----+----------+-------+</span><br><span class="line">| id | name     | score |</span><br><span class="line">+----+----------+-------+</span><br><span class="line">|  <span class="number">1</span> | alicfeng |    <span class="number">75</span> |</span><br><span class="line">|  <span class="number">2</span> | feng     |   <span class="number">100</span> |</span><br><span class="line">|  <span class="number">3</span> | alic     |    <span class="number">90</span> |</span><br><span class="line">+----+----------+-------+</span><br><span class="line"><span class="number">3</span> rows <span class="keyword">in</span> set (<span class="number">0.00</span> sec)</span><br><span class="line"></span><br><span class="line">## (2)事务B新增删除一条数据并提交</span><br><span class="line">mysql&gt; <span class="keyword">delete</span> <span class="keyword">from</span> score where id=<span class="number">1</span>;</span><br><span class="line">Query OK, <span class="number">1</span> row affected (<span class="number">0.01</span> sec)</span><br><span class="line"></span><br><span class="line">mysql&gt; commit;</span><br><span class="line">Query OK, <span class="number">0</span> rows affected (<span class="number">0.01</span> sec)</span><br><span class="line"></span><br><span class="line">## (3)事务A再次读取score数据表</span><br><span class="line">mysql&gt; select * <span class="keyword">from</span> score;</span><br><span class="line">+----+----------+-------+</span><br><span class="line">| id | name     | score |</span><br><span class="line">+----+----------+-------+</span><br><span class="line">|  <span class="number">1</span> | alicfeng |    <span class="number">75</span> |</span><br><span class="line">|  <span class="number">2</span> | feng     |   <span class="number">100</span> |</span><br><span class="line">|  <span class="number">3</span> | alic     |    <span class="number">90</span> |</span><br><span class="line">+----+----------+-------+</span><br><span class="line"><span class="number">3</span> rows <span class="keyword">in</span> set (<span class="number">0.00</span> sec)</span><br></pre></td></tr></table></figure>
<h3 id="MySQL性能突发事件问题排查技巧"><a href="#MySQL性能突发事件问题排查技巧" class="headerlink" title="MySQL性能突发事件问题排查技巧"></a>MySQL性能突发事件问题排查技巧</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">https:<span class="comment">//mp.weixin.qq.com/s/qCRfxIr1RoHd9i8-Hk8iuQ</span></span><br><span class="line">top — Linux 系统进程监控</span><br><span class="line">iostat</span><br><span class="line"> vmstat — 虚拟内存统计</span><br><span class="line">[xxx@localhost ~]$ vmstat</span><br><span class="line">procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----</span><br><span class="line"> r  b   swpd   free   buff  cache   si   so    bi    bo   <span class="keyword">in</span>   cs us sy id wa st</span><br><span class="line"> <span class="number">0</span>  <span class="number">0</span> <span class="number">945448</span> <span class="number">437836</span> <span class="number">618928</span> <span class="number">5950612</span>    <span class="number">1</span>    <span class="number">0</span>    <span class="number">13</span>   <span class="number">685</span>    <span class="number">0</span>    <span class="number">0</span> <span class="number">16</span>  <span class="number">2</span> <span class="number">82</span>  <span class="number">0</span>  <span class="number">0</span></span><br><span class="line"> lsof — 打开文件列表</span><br><span class="line"> [finance@localhost ~]$ lsof -c php-fpm</span><br><span class="line"> COMMAND   PID    USER   FD      TYPE     DEVICE SIZE/OFF       NODE NAME</span><br><span class="line"> php-fpm  <span class="number">3893</span>    root  cwd   unknown                                /proc/<span class="number">3893</span>/cwd (readlink: Permission denied)</span><br><span class="line"> php-fpm  <span class="number">3893</span>    root  rtd   unknown                                /proc/<span class="number">3893</span>/root (readlink: Permission denied)</span><br><span class="line"> php-fpm  <span class="number">3893</span>    root  txt   unknown                                /proc/<span class="number">3893</span>/exe (readlink: Permission denied)</span><br><span class="line"> php-fpm  <span class="number">3893</span>    root NOFD                                          /proc/<span class="number">3893</span>/fd (opendir: Permission denied)</span><br><span class="line"> php-fpm  <span class="number">3894</span> root  cwd       DIR        <span class="number">8</span>,<span class="number">2</span>     <span class="number">4096</span>      <span class="number">90113</span> /root</span><br><span class="line"> php-fpm  <span class="number">3894</span> root  rtd       DIR        <span class="number">8</span>,<span class="number">2</span>     <span class="number">4096</span>          <span class="number">2</span> /</span><br><span class="line"> php-fpm  <span class="number">3894</span> root  txt       REG        <span class="number">8</span>,<span class="number">7</span> <span class="number">37943970</span>     <span class="number">264189</span> /data/php55/sbin/php-fpm</span><br><span class="line">tcpdump — 网络数据包分析器</span><br><span class="line">netstat — 网络统计 监控网络数据包传入和传出的统计界面的命令行工具</span><br><span class="line">[XXX@localhost ~]$ netstat -a |more</span><br><span class="line">Active Internet connections (servers and established)</span><br><span class="line">Proto Recv-Q Send-Q Local Address               Foreign Address             State</span><br><span class="line">tcp        <span class="number">0</span>      <span class="number">0</span> <span class="number">127</span>:<span class="number">6379</span> *:*                         LISTEN</span><br><span class="line">tcp        <span class="number">0</span>      <span class="number">0</span> localhost:<span class="number">6379</span>              *:*                         LISTEN</span><br><span class="line">tcp        <span class="number">0</span>      <span class="number">0</span> localhost:<span class="number">9004</span>              *:*                         LISTEN</span><br><span class="line"></span><br><span class="line">SHOW PROCESSLIST; —当前MySQL数据库的运行的所有线程</span><br><span class="line">INNODB_TRX; — 当前运行的所有事务</span><br><span class="line">mysql&gt; select *<span class="keyword">from</span> information_schema.INNODB_TRX\G</span><br><span class="line">INNODB_LOCKS; — 当前出现的锁</span><br><span class="line">select *<span class="keyword">from</span> information_schema.INNODB_LOCKS\G</span><br><span class="line">INNODB_LOCK_WAITS; — 锁等待的对应关系计</span><br><span class="line">mysql&gt; select *<span class="keyword">from</span> information_schema.INNODB_LOCK_WAITS\G</span><br><span class="line">SHOW OPEN TABLES where In_use &gt;<span class="number">0</span>; — 当前打开表</span><br><span class="line">SHOW ENGINE INNODB STATUS  \G; —Innodb状态</span><br><span class="line">SHOW STATUS LIKE  <span class="string">'innodb_row_lock_%'</span>; — 锁性能状态</span><br><span class="line">SQL语句EXPLAIN; — 查询优化器</span><br></pre></td></tr></table></figure>
<h3 id="Mysql-批量写入数据"><a href="#Mysql-批量写入数据" class="headerlink" title="Mysql 批量写入数据"></a>Mysql 批量写入数据</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line">https:<span class="comment">//my.oschina.net/famoustone/blog/856736</span></span><br><span class="line">public <span class="function"><span class="keyword">function</span> <span class="title">insertTest</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line"></span><br><span class="line">		set_time_limit(<span class="number">0</span>);   <span class="comment">//防止超300s 500错误</span></span><br><span class="line">	</span><br><span class="line">		$t1 = microtime(<span class="literal">true</span>);</span><br><span class="line">	</span><br><span class="line">	</span><br><span class="line">		<span class="comment">//随机插入num条</span></span><br><span class="line">		<span class="keyword">for</span> ($i=<span class="number">1</span>; $i&lt;=<span class="number">200000</span>; $i++)&#123;</span><br><span class="line">			</span><br><span class="line">			$result = $<span class="keyword">this</span>-&gt;db-&gt;insert(<span class="string">'myisam'</span>, [<span class="string">'value'</span> =&gt; uniqid().$i]);</span><br><span class="line">		&#125;</span><br><span class="line"></span><br><span class="line">		<span class="comment">//程序运行时间</span></span><br><span class="line">		$t2 = microtime(<span class="literal">true</span>);</span><br><span class="line">		echo <span class="string">'耗时：'</span>.round($t2-$t1,<span class="number">3</span>).<span class="string">'秒&lt;br&gt;'</span>;</span><br><span class="line">		echo <span class="string">'内存消耗：'</span>.round(memory_get_usage()/<span class="number">1048576</span>,<span class="number">2</span>).<span class="string">" M&lt;br/&gt;"</span>;</span><br><span class="line">	</span><br><span class="line">	&#125;</span><br><span class="line">	    <span class="number">167</span>秒，时间<span class="number">20</span>w 数据 Myisam要 接近<span class="number">3</span>分钟了。</span><br><span class="line">    </span><br><span class="line">my.cnf 当innodb_flush_log_at_trx_commit=<span class="number">2</span>时, 每次事务提交时, MySQL会把log buffer的数据写入log file, 但          不会主动触发flush(刷新到disk)操作同时进行. 然而, MySQL会每秒执行一次flush(刷新到disk)操作.</span><br><span class="line">public <span class="function"><span class="keyword">function</span> <span class="title">insertTest</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line"></span><br><span class="line">		set_time_limit(<span class="number">0</span>);   <span class="comment">//防止超300s 500错误</span></span><br><span class="line">	</span><br><span class="line">		$t1 = microtime(<span class="literal">true</span>);</span><br><span class="line">	</span><br><span class="line">	</span><br><span class="line">		$sql = <span class="string">"insert into innodb (value) VALUES"</span>;</span><br><span class="line">		<span class="comment">//随机插入num条</span></span><br><span class="line">		<span class="keyword">for</span> ($i=<span class="number">1</span>; $i&lt;=<span class="number">200000</span>; $i++)&#123;</span><br><span class="line">			</span><br><span class="line">			$val = uniqid().$i;</span><br><span class="line">				</span><br><span class="line">			$sql .= <span class="string">"('&#123;$val&#125;'),"</span>;</span><br><span class="line">			</span><br><span class="line">		&#125;</span><br><span class="line">		</span><br><span class="line">		$sql = substr($sql,<span class="number">0</span>,<span class="number">-1</span>);</span><br><span class="line">		</span><br><span class="line">		<span class="comment">//程序运行时间</span></span><br><span class="line">		$t2 = microtime(<span class="literal">true</span>);</span><br><span class="line">		echo <span class="string">'循环耗时：'</span>.round($t2-$t1,<span class="number">3</span>).<span class="string">'秒&lt;br&gt;'</span>;</span><br><span class="line">		</span><br><span class="line">		$<span class="keyword">this</span>-&gt;db-&gt;query($sql);  <span class="comment">//批量插入</span></span><br><span class="line">		</span><br><span class="line">		$t3 = microtime(<span class="literal">true</span>);</span><br><span class="line">		echo <span class="string">'插入耗时：'</span>.round($t3-$t2,<span class="number">3</span>).<span class="string">'秒&lt;br&gt;'</span>;</span><br><span class="line">		</span><br><span class="line">		echo <span class="string">'内存消耗：'</span>.round(memory_get_usage()/<span class="number">1048576</span>,<span class="number">2</span>).<span class="string">" M&lt;br/&gt;"</span>;</span><br><span class="line">	</span><br><span class="line">	&#125;拼接语句可能会报错</span><br><span class="line">     设置一下</span><br><span class="line">     </span><br><span class="line">     max_allowed_packet = <span class="number">500</span>M</span><br><span class="line">     </span><br><span class="line">     允许mysql 接受数据包大小。</span><br></pre></td></tr></table></figure>
<h3 id="Redis延时队列"><a href="#Redis延时队列" class="headerlink" title="Redis延时队列"></a>Redis延时队列</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">https:<span class="comment">//rsy.me/posts/redis-application-in-web-development/?hmsr=toutiao.io&amp;utm_medium=toutiao.io&amp;utm_source=toutiao.io</span></span><br><span class="line">$queueKey = <span class="string">"queue"</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 生产者</span></span><br><span class="line">$redis-&gt;rpush($queueKey, $data)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 消费者</span></span><br><span class="line"><span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">    $data = $redis-&gt;lpop($queueKey);</span><br><span class="line">    <span class="keyword">if</span> (<span class="literal">null</span> === $data) &#123;</span><br><span class="line">        usleep(<span class="number">100000</span>);</span><br><span class="line">        <span class="keyword">continue</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 业务逻辑</span></span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">$queueKey = <span class="string">"queue"</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 生产消息</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 消费时间, 这里设置为1小时候</span></span><br><span class="line">$consumeTimestamp = time() + <span class="number">3600</span>;</span><br><span class="line"><span class="comment">// $data需要添加随机串前缀(or后缀)，防止出现重复member被丢弃</span></span><br><span class="line">$data = $data . md5(uniqid(rand(), <span class="literal">true</span>));</span><br><span class="line">$redis-&gt;zadd($queueKey, $consumeTimestamp, $data);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 消费消息</span></span><br><span class="line"><span class="keyword">while</span> (tue) &#123;</span><br><span class="line">    $arrData = $redis-&gt;zrangebyscore($queueKey, <span class="number">0</span>, time());</span><br><span class="line">    <span class="keyword">if</span> (!$arrData) &#123;</span><br><span class="line">        usleep(<span class="number">100000</span>);</span><br><span class="line">        <span class="keyword">continue</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 业务逻辑</span></span><br><span class="line">    foreach ($arrData <span class="keyword">as</span> $data) &#123;</span><br><span class="line">        $data = substr($data, <span class="number">0</span>, strlen($data) - <span class="number">32</span>);</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 消费$data</span></span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="redis-分布式锁"><a href="#redis-分布式锁" class="headerlink" title="redis 分布式锁"></a>redis 分布式锁</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line">$lockStatus = $redis-&gt;setnx($lockKey, <span class="number">1</span>);</span><br><span class="line"><span class="keyword">if</span> (<span class="number">1</span> === $lockStatus) &#123;</span><br><span class="line">    <span class="comment">// 加锁成功，为锁设置超时时间</span></span><br><span class="line">    $redis-&gt;expire($lockKey, <span class="number">300</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 进行后续操作</span></span><br><span class="line"></span><br><span class="line">&#125; elseif (<span class="number">0</span> === $lockStatus) &#123;</span><br><span class="line">    <span class="comment">// 加锁失败</span></span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="comment">// 其他异常</span></span><br><span class="line">&#125;</span><br><span class="line">$lockStatus = $<span class="keyword">this</span>-&gt;redis-&gt;set($lockKey, <span class="number">1</span>, <span class="string">"EX"</span>, <span class="number">30</span>, <span class="string">"NX"</span>);</span><br><span class="line"><span class="keyword">if</span> (<span class="string">"OK"</span> === $lockStatus) &#123;</span><br><span class="line">    <span class="comment">// 加锁成功，可进行后续操作</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">//业务逻辑执行完毕，释放锁</span></span><br><span class="line">    $<span class="keyword">this</span>-&gt;redis-&gt;del($lockKey);</span><br><span class="line"></span><br><span class="line">&#125; elseif (<span class="literal">null</span> === $lockStatus) &#123;</span><br><span class="line">    <span class="comment">// 加锁失败</span></span><br><span class="line">&#125;</span><br><span class="line">$lockToken = md5(uniqid(rand(), <span class="literal">true</span>));</span><br><span class="line"><span class="comment">// 此处超时时间根据具体业务逻辑配置</span></span><br><span class="line">$expire = rand(<span class="number">280</span>, <span class="number">320</span>);</span><br><span class="line">$lockStatus = $<span class="keyword">this</span>-&gt;redis-&gt;set($lockKey, $lockToken, <span class="string">"EX"</span>, $expire, <span class="string">"NX"</span>);</span><br><span class="line"><span class="keyword">if</span> (<span class="string">"OK"</span> === $lockStatus) &#123;</span><br><span class="line">    <span class="comment">// 加锁成功，可进行后续操作</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 业务逻辑执行完毕，释放锁</span></span><br><span class="line">    <span class="comment">// 删除锁之前需要判断是否是自己上的锁</span></span><br><span class="line">    $currentToken = $<span class="keyword">this</span>-&gt;redis-&gt;get($lockKey);</span><br><span class="line">    <span class="keyword">if</span> ($currentToken === $lockToken) &#123;</span><br><span class="line">        $<span class="keyword">this</span>-&gt;redis-&gt;del($lockKey);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125; elseif (<span class="literal">null</span> === $lockStatus) &#123;</span><br><span class="line">    <span class="comment">// 加锁失败</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="redis-无法启动"><a href="#redis-无法启动" class="headerlink" title="redis 无法启动"></a>redis 无法启动</h3><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">redis突然挂掉后，无法启动，查看log日志，发现报Short read or OOM loading DB. Unrecoverable error, aborting now</span><br><span class="line">[root@localhost ~]# rm -f /var/lib/redis/dump.rdb  </span><br><span class="line">[root@localhost ~]# rm -f /var/run/redis.pid  </span><br><span class="line">[root@localhost ~]# service redis start</span><br></pre></td></tr></table></figure>
<h3 id="redis-导出-导入"><a href="#redis-导出-导入" class="headerlink" title="redis 导出 导入"></a>redis 导出 导入</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">[root@localhost tank]# yum install ruby rubygems ruby-devel   //安装rubygems 以及相关包  </span><br><span class="line">  </span><br><span class="line">[root@localhost tank]# gem sources -a http://ruby.taobao.org/   //源，加入淘宝，外面的源不能访问  </span><br><span class="line">http:<span class="comment">//ruby.taobao.org/ added to sources  </span></span><br><span class="line">  </span><br><span class="line">[root@localhost tank]# gem install redis-dump -V   //安装redis-dump </span><br><span class="line">查看复制打印?</span><br><span class="line">[root@localhost tank]# telnet 127.0.0.1 6379 //telnet到redis  </span><br><span class="line">Trying <span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>...  </span><br><span class="line">Connected to <span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>.  </span><br><span class="line">Escape character is <span class="string">'^]'</span>.  </span><br><span class="line">set test <span class="number">11</span> <span class="comment">//设置一个值  </span></span><br><span class="line">+OK  </span><br><span class="line">get test <span class="comment">//取值  </span></span><br><span class="line">$<span class="number">2</span>  </span><br><span class="line"><span class="number">11</span>  </span><br><span class="line">  </span><br><span class="line">[root@localhost tank]# redis-dump -u 127.0.0.1:6379 &gt;test.json //导出数据  </span><br><span class="line">[root@localhost tank]# telnet 127.0.0.1 6379 //telnet到redis  </span><br><span class="line">Trying <span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>...  </span><br><span class="line">Connected to <span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>.  </span><br><span class="line">Escape character is <span class="string">'^]'</span>.  </span><br><span class="line">flushall <span class="comment">//请空所有数据  </span></span><br><span class="line">+OK  </span><br><span class="line">keys * <span class="comment">//查看已清空  http://blog.51yip.com/nosql/1656.html</span></span><br><span class="line">*<span class="number">0</span>  </span><br><span class="line">  </span><br><span class="line">[root@localhost tank]# &lt; test.json redis-load //导入数据  </span><br><span class="line">  </span><br><span class="line">[root@localhost tank]# telnet 127.0.0.1 6379  </span><br><span class="line">Trying <span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>...  </span><br><span class="line">Connected to <span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>.  </span><br><span class="line">Escape character is <span class="string">'^]'</span>.  </span><br><span class="line">keys * <span class="comment">//已导入成功  </span></span><br><span class="line">*<span class="number">1</span>  </span><br><span class="line">$<span class="number">4</span>  </span><br><span class="line">test</span><br></pre></td></tr></table></figure>
<h3 id="优化not-in-和-lt-gt-查询"><a href="#优化not-in-和-lt-gt-查询" class="headerlink" title="优化not in 和&lt;&gt;查询"></a>优化not in 和&lt;&gt;查询</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">http:<span class="comment">//fanqieto.top/2017/11/26/mysql%E6%9F%A5%E8%AF%A2%E4%BC%98%E5%8C%96/</span></span><br><span class="line">select customer_id,first_name,last_name,email</span><br><span class="line"><span class="keyword">from</span> customer</span><br><span class="line">where customer_id</span><br><span class="line">not <span class="keyword">in</span> (select customer_id <span class="keyword">from</span> payment)</span><br><span class="line">改为：</span><br><span class="line"></span><br><span class="line">select a.customer_id,a.first_name,a.last_name,a.email </span><br><span class="line"><span class="keyword">from</span> customer a</span><br><span class="line">left join payment b on a.customer_id = b.customer_id</span><br><span class="line">where b.customer_id is <span class="literal">null</span> m</span><br><span class="line">使用汇总表优化查询</span><br><span class="line">例子</span><br><span class="line"></span><br><span class="line">select count(*) <span class="keyword">from</span> product_comment where product_id = <span class="number">999</span></span><br><span class="line">改为</span><br><span class="line"></span><br><span class="line">create table product_comment_cnt(product_id int, cnt int);</span><br><span class="line">select sum(cnt) <span class="keyword">from</span> (</span><br><span class="line">select cnt <span class="keyword">from</span> product_comment_cnt where product_id = <span class="number">999</span></span><br><span class="line">union all</span><br><span class="line">select count(*) <span class="keyword">from</span> product_comment where product_id = <span class="number">999</span></span><br><span class="line">and timestr &gt; date(now())</span><br><span class="line">) a</span><br></pre></td></tr></table></figure>
<h3 id="Redis的n种妙用"><a href="#Redis的n种妙用" class="headerlink" title="Redis的n种妙用"></a>Redis的n种妙用</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line">setnx key value，当key不存在时，将 key 的值设为 value ，返回<span class="number">1</span>。若给定的 key 已经存在，则setnx不做任何动作，返回<span class="number">0</span>。</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">当setnx返回<span class="number">1</span>时，表示获取锁，做完操作以后del key，表示释放锁，如果setnx返回<span class="number">0</span>表示获取锁失败</span><br><span class="line"># 实现方式一</span><br><span class="line"># 一直往list左边放</span><br><span class="line">lpush key value </span><br><span class="line"># key这个list有元素时，直接弹出，没有元素被阻塞，直到等待超时或发现可弹出元素为止，上面例子超时时间为10s</span><br><span class="line">brpop key value <span class="number">10</span> </span><br><span class="line"></span><br><span class="line"># 实现方式二</span><br><span class="line">rpush key value</span><br><span class="line">blpop key value <span class="number">10</span></span><br><span class="line"># 参加抽奖活动</span><br><span class="line">sadd key &#123;userId&#125; </span><br><span class="line"></span><br><span class="line"># 获取所有抽奖用户，大轮盘转起来</span><br><span class="line">smembers key </span><br><span class="line"></span><br><span class="line"># 抽取count名中奖者，并从抽奖活动中移除</span><br><span class="line">spop key count </span><br><span class="line"></span><br><span class="line"># 抽取count名中奖者，不从抽奖活动中移除</span><br><span class="line">srandmember key count</span><br><span class="line"># 1001用户给8001帖子点赞</span><br><span class="line">sadd like::<span class="number">8001</span> <span class="number">1001</span></span><br><span class="line"></span><br><span class="line"># 取消点赞</span><br><span class="line">srem like::<span class="number">8001</span> <span class="number">1001</span></span><br><span class="line"></span><br><span class="line"># 检查用户是否点过赞</span><br><span class="line">sismember like::<span class="number">8001</span> <span class="number">1001</span> </span><br><span class="line"></span><br><span class="line"># 获取点赞的用户列表</span><br><span class="line">smembers like::<span class="number">8001</span> </span><br><span class="line"></span><br><span class="line"># 获取点赞用户数</span><br><span class="line">scard like::<span class="number">8001</span> </span><br><span class="line"># 返回sevenSub和qingSub的交集，即seven和青山的共同关注</span><br><span class="line">sinter sevenSub qingSub -&gt; &#123;mic,james&#125;</span><br><span class="line"></span><br><span class="line"># 我关注的人也关注他,下面例子中我是seven</span><br><span class="line"># qing在micSub中返回1，否则返回0</span><br><span class="line">sismember micSub qing</span><br><span class="line">sismember jamesSub qing</span><br><span class="line"></span><br><span class="line"># 我可能认识的人,下面例子中我是seven</span><br><span class="line"># 求qingSub和sevenSub的差集，并存在sevenMayKnow集合中</span><br><span class="line">sdiffstore sevenMayKnow qingSub sevenSub -&gt; &#123;seven,jack&#125;</span><br><span class="line"># 将拯救者y700P-001和ThinkPad-T480这两个元素放到集合brand::lenovo</span><br><span class="line">sadd brand::lenovo 拯救者y700P<span class="number">-001</span> ThinkPad-T480</span><br><span class="line">sadd screenSize::<span class="number">15.6</span> 拯救者y700P<span class="number">-001</span> 机械革命Z2AIR</span><br><span class="line">sadd processor::i7 拯救者y700P<span class="number">-001</span> 机械革命X8TIPlus</span><br><span class="line"></span><br><span class="line"># 获取品牌为联想，屏幕尺寸为15.6，并且处理器为i7的电脑品牌(sinter为获取集合的交集)</span><br><span class="line">sinter brand::lenovo screenSize::<span class="number">15.6</span> processor::i7 -&gt; 拯救者y700P<span class="number">-001</span></span><br><span class="line"># user1的用户分数为 10</span><br><span class="line">zadd ranking <span class="number">10</span> user1</span><br><span class="line">zadd ranking <span class="number">20</span> user2</span><br><span class="line"></span><br><span class="line"># 取分数最高的3个用户</span><br><span class="line">zrevrange ranking <span class="number">0</span> <span class="number">2</span> withscores</span><br><span class="line">Redis 的持久化机制有两种，第一种是快照（RDB RDB是隔一段时间来备份数据），第二种是 AOF 日志。快照是一次全量备份，AOF 日志是连续的增量备份。快照是内存数据的二进制序列化形式，在存储上非常紧凑，而 AOF 日志记录的是内存数据修改的指令记录文本。AOF 日志在长期的运行过程中会变的无比庞大，数据库重启时需要加载 AOF 日志进行指令重放，这个时间就会无比漫长。所以需要定期进行 AOF 重写，给 AOF 日志进行瘦身。</span><br><span class="line">假如客户端每秒发送<span class="number">5000</span>个请求，其中<span class="number">4000</span>个为黑客的恶意攻击，即在数据库中也查不到。举个例子，用户id为正数，黑客构造的用户id为负数，</span><br><span class="line"></span><br><span class="line">如果黑客每秒一直发送这<span class="number">4000</span>个请求，缓存就不起作用，数据库也很快被打死。</span><br><span class="line">如何解决缓存穿透</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">查询不到的数据也放到缓存，value为空，如set <span class="number">-999</span> “”</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">总而言之，缓存雪崩就是缓存失效，请求全部全部打到数据库，数据库瞬间被打死。缓存穿透就是查询了一个一定不存在的数据，并且从存储层查不到的数据没有写入缓存，这将导致这个不存在的数据每次请求都要到存储层去查询，失去了缓存的意义</span><br><span class="line">https:<span class="comment">//www.itcodemonkey.com/article/12951.html</span></span><br></pre></td></tr></table></figure>
<h3 id="防止库存超卖"><a href="#防止库存超卖" class="headerlink" title="防止库存超卖"></a>防止库存超卖</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">https:<span class="comment">//www.fanhaobai.com/2017/09/record-question-1.html</span></span><br><span class="line"></span><br><span class="line">$num = $redis-&gt;incr($key);</span><br><span class="line"><span class="keyword">if</span> ($num &lt; $max) &#123;</span><br><span class="line">    <span class="comment">//入抢购成功队列，异步去执行抢购成功逻辑</span></span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="comment">//不好意思呢，已经被抢完了</span></span><br><span class="line">&#125;</span><br><span class="line">不知道你有没有闻到这段代码的坏味道，在大部分情况下会如你所想地运行，但是特殊场景下会 出现判断失效 的逻辑问题，例如：</span><br><span class="line"></span><br><span class="line"><span class="number">1</span>、key 由于某些原因失效了；</span><br><span class="line"><span class="number">2</span>、Incr 操作失败了，不会抛异常并返回 <span class="literal">false</span>；</span><br><span class="line">通过日志定位到 Incr 操作问题，便 Telnet 连接到线上 Redis 服务，发现了异常情况：</span><br><span class="line"></span><br><span class="line"># 查看值</span><br><span class="line">GET key</span><br><span class="line"><span class="number">100</span></span><br><span class="line"># 尝试修改</span><br><span class="line">INCR key</span><br><span class="line">READONLY You can<span class="string">'t write against a read only slave</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">INFO</span></span><br><span class="line"><span class="string"># Replication</span></span><br><span class="line"><span class="string">role:slave</span></span><br><span class="line"><span class="string">可以看出来，该连接的机器目前处于从机状态，不可写操作，所以 Incr 操作返回 false，同时 PHP 不同类型比较会存在隐式转化，所以false &lt; $num恒成立，导致计数器失效。</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">增加计数器容错处理：</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">$num = $redis-&gt;incr($key);</span></span><br><span class="line"><span class="string">if ($num &gt; 0 &amp;&amp; $num &lt; $max) &#123;</span></span><br><span class="line"><span class="string">    //入抢购成功队列，异步去执行抢购成功逻辑</span></span><br><span class="line"><span class="string">&#125; else &#123;</span></span><br><span class="line"><span class="string">    //不好意思呢，已经被抢完了</span></span><br><span class="line"><span class="string">&#125;</span></span><br><span class="line"><span class="string">然后，切换 Redis 源到高可用集群（Codis），测试并重新上线，第二日的抢购已经正常，看着 Cat 上流量逐渐平稳，心里也踏实了。</span></span><br></pre></td></tr></table></figure>
<h3 id="Redis管道提升性能"><a href="#Redis管道提升性能" class="headerlink" title="Redis管道提升性能"></a>Redis管道提升性能</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">Redis 的 管道 （pipelining）是用来打包多条无关命令批量执行，以减少多个命令分别执行带来的网络交互时间。在一些批量操作数据的场景，使用管道可以显著提升 Redis 的读写性能</span><br><span class="line"></span><br><span class="line">https:<span class="comment">//www.fanhaobai.com/2017/08/redis-pipelining.html</span></span><br><span class="line"># 安装nc命令</span><br><span class="line">$ yum install nc</span><br><span class="line"># nc打包多个命令</span><br><span class="line">$ (printf <span class="string">"PING\r\nPING\r\nPING\r\n"</span>) | nc localhost <span class="number">6379</span></span><br><span class="line"># 响应</span><br><span class="line">+PONG</span><br><span class="line">+PONG</span><br><span class="line">+PONG</span><br><span class="line">$start = nowTime();</span><br><span class="line">foreach (range(<span class="number">1</span>, <span class="number">1000</span>) <span class="keyword">as</span> $id) &#123;</span><br><span class="line">    $user[] = $redis-&gt;hgetAll($keyPrex.$id);</span><br><span class="line">&#125;</span><br><span class="line">echo <span class="string">'时间：'</span>, nowTime() - $start, <span class="string">'ms'</span>, PHP_EOL;</span><br><span class="line"></span><br><span class="line">时间：<span class="number">39</span>ms</span><br><span class="line">$start = nowTime();</span><br><span class="line">$redis-&gt;multi(Redis::PIPELINE);</span><br><span class="line">foreach (range(<span class="number">1</span>, <span class="number">1000</span>) <span class="keyword">as</span> $id) &#123;</span><br><span class="line">    <span class="comment">//返回资源id相同的socket资源，并未执行命令</span></span><br><span class="line">    $redis-&gt;hgetAll($keyPrex.$id);  </span><br><span class="line">&#125;</span><br><span class="line">$user = $redis-&gt;exec();</span><br><span class="line">echo <span class="string">'时间：'</span>, nowTime() - $start, <span class="string">'ms'</span>, PHP_EOL;</span><br><span class="line"></span><br><span class="line">时间：<span class="number">6</span>ms</span><br><span class="line">在批量操作（查询和写入）数据时，我们应尽量避免多次跟 Redis 的网络交互。这时，可以使用管道实现，也可以 Redis 内嵌 Lua 脚本实现。需要注意的是：</span><br><span class="line"></span><br><span class="line">管道只适用于无因果关联的多命令操作，否则就需要借助 Lua 脚本实现批量操作；</span><br><span class="line">在实际应用中，Redis 往往不可能是单机部署，如果想要在集群中使用管道，可以部署为一主多从架构，此时所有节点的数据都一致，随机选取节点使用管道即可；</span><br><span class="line">总结</span><br><span class="line"></span><br><span class="line">在批量获取数据时，尽管使用 Redis 的管道性能会显著提升，但是使用管道时 Redis 会缓存之前命令的结果，最后一并输出给终端，因此所打包的命令不宜太多，否则内存使用会很严重。</span><br></pre></td></tr></table></figure>
<h3 id="处理重复数据"><a href="#处理重复数据" class="headerlink" title="处理重复数据"></a>处理重复数据</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">CREATE TABLE <span class="string">`allowed_user`</span></span><br><span class="line">(</span><br><span class="line">  <span class="string">`id`</span> INT(<span class="number">10</span>) UNSIGNED AUTO_INCREMENT PRIMARY KEY,</span><br><span class="line">  <span class="string">`uid`</span> VARCHAR(<span class="number">36</span>)  DEFAULT <span class="string">''</span>  NOT NULL,</span><br><span class="line">  <span class="string">`last_time`</span> TIMESTAMP  NOT NULL,</span><br><span class="line">  UNIQUE (uid)</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">INSERT INTO <span class="string">`allowed_user`</span> (<span class="string">`uid`</span>, <span class="string">`last_time`</span>) VALUES (<span class="string">'8e9b8c14-fae8-49d4-bbac-a733c09ec82f'</span>, <span class="string">'2017-09-03 19:31:15'</span>)</span><br><span class="line">REPLACE INTO <span class="string">`allowed_user`</span> (<span class="string">`uid`</span>, <span class="string">`last_time`</span>) VALUES (<span class="string">'8e9b8c14-fae8-49d4-bbac-a733c09ec82f'</span>, <span class="string">'2017-09-01 19:31:15'</span>)</span><br><span class="line">注意执行影响行数为 <span class="number">2</span></span><br><span class="line">INSERT INTO <span class="string">`allowed_user`</span> (<span class="string">`uid`</span>, <span class="string">`last_time`</span>) VALUES (<span class="string">'8e9b8c14-fae8-49d4-bbac-a733c09ec82f'</span>, <span class="string">'2017-09-01 19:31:15'</span>) ON DUPLICATE  KEY UPDATE <span class="string">`last_time`</span> = <span class="string">'2017-09-01 19:40:15'</span></span><br><span class="line">SQL 执行影响记录数为 <span class="number">2</span> 条</span><br><span class="line">INSERT IGNORE INTO <span class="string">`allowed_user`</span> (<span class="string">`uid`</span>, <span class="string">`last_time`</span>) VALUES (<span class="string">'8e9b8c14-fae8-49d4-bbac-a733c09ec82f'</span>, <span class="string">'2017-09-01 19:41:15'</span>)</span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">    $user = $model-&gt;query(<span class="string">"SELECT * FROM `allowed_user` WHERE `uid` = '8e9b8c14-fae8-49d4-bbac-a733c09ec82f'"</span>);</span><br><span class="line">    <span class="keyword">if</span> (user) &#123;</span><br><span class="line">       $model-&gt;exec(<span class="string">"UPDATE `allowed_user` SET `last_time` = '2017-09-01 19:50:15' WHERE `uid` = '8e9b8c14-fae8-49d4-bbac-a733c09ec82f'"</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">       $model-&gt;exec(<span class="string">"INSERT INTO `allowed_user` (`uid`, `last_time`) VALUES ('8e9b8c14-fae8-49d4-bbac-a733c09ec82f', '2017-09-01 19:50:15'"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125; <span class="keyword">catch</span>(Exception $e) &#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">这段代码通过程序逻辑去试图保证唯一性，但是在高并发情况下，并不能保证数据唯一性，因为不是原子性操作，修改后为：https:<span class="comment">//www.fanhaobai.com/2017/09/mysql-repetition-deal.html</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">    $model-&gt;exec(<span class="string">"INSERT INTO `allowed_user` (`uid`, `last_time`) VALUES ('8e9b8c14-fae8-49d4-bbac-a733c09ec82f', '2017-09-01 19:50:15') ON DUPLICATE  KEY UPDATE `last_time` = '2017-09-01 19:50:15'"</span>);</span><br><span class="line">&#125; <span class="keyword">catch</span>(Exception $e) &#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">替换掉异常数据的特殊换行符即可。</span><br><span class="line"></span><br><span class="line">UPDATE table_a SET uid = REPLACE(REPLACE(uid, CHAR(<span class="number">10</span>), <span class="string">''</span>), CHAR(<span class="number">13</span>), <span class="string">''</span>);</span><br><span class="line">在 MySQL 中，CHAR(<span class="number">10</span>) 和 CHAR(<span class="number">13</span>) 分别代 换行符 和 回车符，这里都替换掉。</span><br></pre></td></tr></table></figure>
<h3 id="lua-抢购场景"><a href="#lua-抢购场景" class="headerlink" title="lua 抢购场景"></a>lua 抢购场景</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line">$key = <span class="string">'number:string'</span>;</span><br><span class="line">$redis = <span class="keyword">new</span> Redis();</span><br><span class="line">$number = $redis-&gt;get($key);</span><br><span class="line"><span class="keyword">if</span> ($number &lt;= <span class="number">0</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line">$redis-&gt;decr($key);</span><br><span class="line"><span class="keyword">return</span> $number--;</span><br><span class="line">local key = <span class="string">'number:string'</span></span><br><span class="line">local number = tonumber(redis.call(<span class="string">"GET"</span>, key))</span><br><span class="line"><span class="keyword">if</span> number &lt;= <span class="number">0</span> then</span><br><span class="line">   <span class="keyword">return</span> <span class="number">0</span></span><br><span class="line">end</span><br><span class="line">redis.call(<span class="string">"DECR"</span>, key)</span><br><span class="line"><span class="keyword">return</span> number--</span><br><span class="line">Redis 中嵌入 Lua 脚本，所具有的几个特性为：</span><br><span class="line"></span><br><span class="line">原子操作：Redis 将整个 Lua 脚本作为一个原子执行，无需考虑并发，无需使用事务来保证数据一致性；</span><br><span class="line">高性能：嵌入 Lua 脚本后，可以减少多个命令执行的网络开销，进而间接提高 Redis 性能；</span><br><span class="line">可复用：Lua 脚本会保存于 Redis 中，客户端都可以使用这些脚本；</span><br><span class="line">Redis 中执行 Lua 脚本都是以原子方式执行，所以是原子操作。另外，redis-cli 命令行客户端支持直接使用--<span class="built_in">eval</span> lua_file参数执行 Lua 脚本。</span><br><span class="line">&gt; EVAL <span class="string">"return &#123;KEYS[1],KEYS[2],ARGV[1],ARGV[2]&#125;"</span> <span class="number">2</span> key1 key2 first second</span><br><span class="line"><span class="number">1</span>) <span class="string">"key1"</span></span><br><span class="line"><span class="number">2</span>) <span class="string">"key2"</span></span><br><span class="line"><span class="number">3</span>) <span class="string">"first"</span></span><br><span class="line"><span class="number">4</span>) <span class="string">"second"</span></span><br><span class="line">&gt; EVAL <span class="string">"return 3.333"</span> <span class="number">0</span></span><br><span class="line">(integer) <span class="number">3</span></span><br><span class="line">&gt; EVAL <span class="string">"return 'fhb'"</span> <span class="number">0</span></span><br><span class="line"><span class="string">"fhb"</span></span><br><span class="line">&gt; EVAL <span class="string">"return &#123;'fhb', 'lw', 'lbf'&#125;"</span> <span class="number">0</span></span><br><span class="line"><span class="number">1</span>) <span class="string">"fhb"</span></span><br><span class="line"><span class="number">2</span>) <span class="string">"lw"</span></span><br><span class="line"><span class="number">3</span>) <span class="string">"lbf"</span></span><br><span class="line">&gt; EVAL <span class="string">"return false"</span> <span class="number">0</span></span><br><span class="line">(nil)</span><br><span class="line">&gt; EVAL <span class="string">"return true"</span> <span class="number">0</span></span><br><span class="line">(integer) <span class="number">1</span></span><br><span class="line">通过 Lua 实现一个针对用户的 API 访问速率控制，Lua 代码如下：</span><br><span class="line"></span><br><span class="line">local key = <span class="string">"rate.limit:string:"</span> .. KEYS[<span class="number">1</span>]</span><br><span class="line">local limit = tonumber(ARGV[<span class="number">1</span>])</span><br><span class="line">local expire_time = tonumber(ARGV[<span class="number">2</span>])</span><br><span class="line">local times = redis.call(<span class="string">"INCR"</span>, key)</span><br><span class="line"><span class="keyword">if</span> times == <span class="number">1</span> then</span><br><span class="line">    redis.call(<span class="string">"EXPIRE"</span>, key, expire_time)</span><br><span class="line">end</span><br><span class="line"><span class="keyword">if</span> times &gt; limit then</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span></span><br><span class="line">end</span><br><span class="line"><span class="keyword">return</span> <span class="number">1</span></span><br><span class="line">KEYS[<span class="number">1</span>] 可以用 API 的 URI + 用户 uid 组成，ARGV[<span class="number">1</span>] 为单位时间限制访问的次数，ARGV[<span class="number">2</span>] 为限制的单位时间。</span><br><span class="line">&gt; EVAL <span class="string">"return redis.call('SET', 'name', 'fhb')"</span> <span class="number">0</span></span><br><span class="line">&gt; EVAL <span class="string">"return redis.pcall('GET', 'name')"</span> <span class="number">0</span></span><br><span class="line"><span class="string">"fhb"</span></span><br><span class="line">https:<span class="comment">//www.fanhaobai.com/2017/09/lua-in-redis.html</span></span><br></pre></td></tr></table></figure>
<h3 id="缓存与数据库双写一致性问题"><a href="#缓存与数据库双写一致性问题" class="headerlink" title="缓存与数据库双写一致性问题"></a>缓存与数据库双写一致性问题</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line">周所周知，在项目性能优化、提升的时候，我们引进了一个缓存的概念，即一款缓存数据的技术，项目在最初期架构规划时都会引进的一个组件。使用缓存有很多好处：加快请求的响应速度、减少数据库的交互与浪费大量的IO操作等，但是在某些场景下使用缓存也有可能会造成雪崩、剧透、数据不一致等问题，我们研究下使用缓存会导致有哪些数据不一致的情况发生以及在哪些场景会使用哪些具体的解决方案，首先我们必然还是会使用缓存的。</span><br><span class="line"></span><br><span class="line">缓存更新策略</span><br><span class="line"></span><br><span class="line">先更新数据库再更新缓存</span><br><span class="line"></span><br><span class="line">浪费资源</span><br><span class="line">每次去更新数据库再更新缓存都是需要申请CPU进行数据库的修改的，同时倘若数据的修改比较频繁以及数据的读操作却又比较少的时候，这种策略会导致出现冷数据的情况。</span><br><span class="line">数据脏读</span><br><span class="line">如果两个操作同时对数据进行操作时，举个栗子：线程A 在线程B更新数据库成功后、更新缓存成功之前读取到数据，也就是读取到了缓存的旧数据。</span><br><span class="line">该策略比较适合更新的频次比较少的场景下，比如博客的文章、基础数据、个人信息等场景。</span><br><span class="line">先更新数据库再删除缓存</span><br><span class="line"></span><br><span class="line">数据脏读</span><br><span class="line">一个请求处理中过程中，倘若数据库更新成功了但是缓存更新失败了，那么后面的请求读取的数据都是旧数据、则脏数据。可以通过缓存过期时间定义缓存的有效期(推荐)，或者使用消息队列在删除缓存失败的时候再次异步更新缓存，直到成功为止，这两种方案都是尽可能减少读取脏数据的方案，还有一种方案可以完全解决数据脏读，就是异步请求串行化，一个字锁，但是会增加业务处理的时间甚至会出现死锁的情况。</span><br><span class="line">这种缓存操作的策略使用的情况被使用的比较多、使用的场景也比较广泛。</span><br><span class="line">先删除缓存再更新数据库</span><br><span class="line">数据脏读</span><br><span class="line">与第二种情况类似，但是更容易出现数据脏读，比如：删除缓存失败更新数据库成功(一般的业务可能在缓存修改失败后不再进行数据库的更新了)、线程B读取了线程A已经成功删除了缓存后更新数据库之前读取了脏数据并且也导致缓存的数据也是旧数据。解决方案还是使用缓存过期时间或者消息队列，在缓存过期的时候务必要注意雪崩的问题，比如大批量数据的过期时间几乎集中在同一个时间点上，容易造成雪崩。</span><br><span class="line"></span><br><span class="line">VARCHAR(N) 中的 N 代表的是字符数，而不是字节数。使用 UTF8 存储 <span class="number">255</span> 个汉字 Varchar(<span class="number">255</span>)=<span class="number">765</span> 个字节。过大的长度会消耗更多的内存</span><br><span class="line"> 优先选择符合存储需要的最小的数据类型</span><br><span class="line"> 方法</span><br><span class="line"> <span class="number">1</span>、将字符串转换成数字类型存储，如：将IP地址转换成整形数据。</span><br><span class="line"> </span><br><span class="line"> MySQL 提供了两个方法来处理 IP 地址</span><br><span class="line"> </span><br><span class="line"> inet_aton 把ip转为无符号整型(<span class="number">4</span><span class="number">-8</span>位)</span><br><span class="line"> inet_ntoa 把整型的ip转为地址</span><br><span class="line"> 插入数据前，先用 inet_aton 把 IP 地址转为整型，可以节省空间。显示数据时，使用 inet_ntoa 把整型的 IP 地址转为地址显示即可。</span><br><span class="line"> </span><br><span class="line"> <span class="number">2</span>、对于非负型的数据（如自增 ID、整型 IP）来说，要优先使用无符号整型来存储,因为无符号相对于有符号可以多出一倍的存储空间。</span><br><span class="line"> SIGNED INT <span class="number">-2147483648</span>~<span class="number">2147483647</span></span><br><span class="line"> UNSIGNED INT <span class="number">0</span>~<span class="number">4294967295</span></span><br><span class="line"> 同财务相关的金额类数据必须使用 decimal 类型</span><br><span class="line"> </span><br><span class="line"> 非精准浮点：float，double</span><br><span class="line"> 精准浮点：decimal</span><br><span class="line"> Decimal 类型为精准浮点数，在计算时不会丢失精度。占用空间由定义的宽度决定，每 <span class="number">4</span> 个字节可以存储 <span class="number">9</span> 位数字，并且小数点要占用一个字节。可用于存储比 bigint 更大的整型数据。</span><br><span class="line">  避免数据类型的隐式转换</span><br><span class="line"> </span><br><span class="line"> 隐式转换会导致索引失效。如：</span><br><span class="line"> select name,phone <span class="keyword">from</span> customer where id = <span class="string">'111'</span>;</span><br><span class="line"> https:<span class="comment">//learnku.com/articles/25020#topnav</span></span><br></pre></td></tr></table></figure>
<h3 id="MongoDB读写分离"><a href="#MongoDB读写分离" class="headerlink" title="MongoDB读写分离"></a>MongoDB读写分离</h3><p>PHP7中的MongoDB\Driver\ReadPreference MongoDB读写分离（Read Preference）的几种模式</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> integer RP_PRIMARY = <span class="number">1</span> ;</span><br><span class="line"><span class="keyword">const</span> integer RP_PRIMARY_PREFERRED = <span class="number">5</span> ;</span><br><span class="line"><span class="keyword">const</span> integer RP_SECONDARY = <span class="number">2</span> ;</span><br><span class="line"><span class="keyword">const</span> integer RP_SECONDARY_PREFERRED = <span class="number">6</span> ;</span><br><span class="line"><span class="keyword">const</span> integer RP_NEAREST = <span class="number">10</span> ;</span><br><span class="line"></span><br><span class="line">primary</span><br><span class="line">主节点，默认模式，读操作只在主节点，如果主节点不可用，报错或者抛出异常。</span><br><span class="line"></span><br><span class="line">primaryPreferred</span><br><span class="line">首选主节点，大多情况下读操作在主节点，如果主节点不可用，如故障转移，读操作在从节点。</span><br><span class="line"></span><br><span class="line">secondary</span><br><span class="line">从节点，读操作只在从节点， 如果从节点不可用，报错或者抛出异常。</span><br><span class="line"></span><br><span class="line">secondaryPreferred</span><br><span class="line">首选从节点，大多情况下读操作在从节点，特殊情况（如单主节点架构）读操作在主节点。</span><br><span class="line"></span><br><span class="line">nearest</span><br><span class="line">最邻近节点，读操作在最邻近的成员，可能是主节点或者从节点</span><br><span class="line">在使用mongo副本集的时候就在想，这些副本不用来读太浪费了，再翻阅php的mongodb驱动，发现一个美好的readPreference，可以设定读取的优先级，其中就有优先读取副本，甚至还可以设定读取最小网络延迟的节点，具体可以参考：http:<span class="comment">//php.net/manual/zh/mongodb-driver-readpreference.construct.php</span></span><br><span class="line">http:<span class="comment">//imhuchao.com/918.html</span></span><br><span class="line">写入安全级别的使用</span><br><span class="line">W选项</span><br><span class="line"></span><br><span class="line"><span class="number">0</span>：非确认式写入</span><br><span class="line"></span><br><span class="line"><span class="number">1</span>：确认式写入</span><br><span class="line"></span><br><span class="line">说明：这个级别下，对副本级只对主库做确认写入</span><br><span class="line"></span><br><span class="line"><span class="number">2</span>：副本级确认式写入</span><br><span class="line"></span><br><span class="line">说明：这个级别下，副本集第一个slave写入成功后就响应给client</span><br><span class="line"></span><br><span class="line">majority：复制级更多slave写入成功后，在响应给client</span><br><span class="line">$filter = array();</span><br><span class="line">$options = array(</span><br><span class="line">    <span class="comment">/* Only return the following fields in the matching documents */</span></span><br><span class="line">    <span class="string">"projection"</span> =&gt; array(</span><br><span class="line">        <span class="string">"title"</span> =&gt; <span class="number">1</span>,</span><br><span class="line">        <span class="string">"article"</span> =&gt; <span class="number">1</span>,</span><br><span class="line">    ),</span><br><span class="line">    <span class="string">"sort"</span> =&gt; array(</span><br><span class="line">        <span class="string">"views"</span> =&gt; <span class="number">-1</span>,</span><br><span class="line">    ),</span><br><span class="line">    <span class="string">"modifiers"</span> =&gt; array(</span><br><span class="line">        <span class="string">'$comment'</span>   =&gt; <span class="string">"This is a query comment"</span>,</span><br><span class="line">        <span class="string">'$maxTimeMS'</span> =&gt; <span class="number">100</span>,</span><br><span class="line">    ),</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">$query = <span class="keyword">new</span> MongoDB\Driver\Query($filter, $options);</span><br><span class="line"></span><br><span class="line">$manager = <span class="keyword">new</span> MongoDB\Driver\Manager(<span class="string">"mongodb://localhost:27017"</span>);</span><br><span class="line">$readPreference = <span class="keyword">new</span> MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_PRIMARY);</span><br><span class="line">$cursor = $manager-&gt;executeQuery(<span class="string">"databaseName.collectionName"</span>, $query, $readPreference);</span><br><span class="line"></span><br><span class="line">foreach($cursor <span class="keyword">as</span> $<span class="built_in">document</span>) &#123;</span><br><span class="line">    var_dump($<span class="built_in">document</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">vi config/database.php</span><br><span class="line"><span class="string">"mongodb"</span> =&gt; [</span><br><span class="line">            <span class="string">'driver'</span> =&gt; <span class="string">'mongodb'</span>,</span><br><span class="line">            <span class="string">'host'</span> =&gt; env(<span class="string">'MONGO_DEFAULT_HOST'</span>, <span class="string">'172.1.7.21'</span>),</span><br><span class="line">            <span class="string">'port'</span> =&gt; env(<span class="string">'MONGO_DEFAULT_PORT'</span>, <span class="number">27017</span>),</span><br><span class="line">            <span class="string">'database'</span> =&gt; env(<span class="string">'MONGO_DEFAULT_DATABASE'</span>, <span class="string">'app'</span>),</span><br><span class="line">            <span class="string">'username'</span> =&gt; env(<span class="string">'MONGO_DEFAULT_USER'</span>, <span class="string">''</span>),</span><br><span class="line">            <span class="string">'password'</span> =&gt; env(<span class="string">'MONGO_DEFAULT_PASSWORD'</span>, <span class="string">''</span>),</span><br><span class="line">            <span class="string">'options'</span> =&gt; [</span><br><span class="line">                <span class="string">'replicaSet'</span> =&gt; env(<span class="string">'MONGO_DEFAULT_REPLICASET'</span>),</span><br><span class="line">                <span class="string">'readPreference'</span>=&gt; env(<span class="string">'MONGO_READ_PREFERENCE'</span>, <span class="string">'nearest'</span>),</span><br><span class="line">            ]</span><br><span class="line">        ],</span><br><span class="line">vi  /vendor/jenssegers/mongodb/src/Jenssegers/Mongodb/Connection.php:<span class="number">28</span></span><br><span class="line">public <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">array $config</span>)</span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        $<span class="keyword">this</span>-&gt;config = $config;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// Build the connection string</span></span><br><span class="line">        $dsn = $<span class="keyword">this</span>-&gt;getDsn($config);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// You can pass options directly to the MongoClient constructor</span></span><br><span class="line">        $options = array_get($config, <span class="string">'options'</span>, []);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// Create the connection</span></span><br><span class="line">        $<span class="keyword">this</span>-&gt;connection = $<span class="keyword">this</span>-&gt;createConnection($dsn, $config, $options);</span><br><span class="line">        dd($<span class="keyword">this</span>-&gt;connection-&gt;getReadPreference());</span><br><span class="line">        array:<span class="number">1</span> [▼</span><br><span class="line">          <span class="string">"type"</span> =&gt; <span class="string">"nearest"</span></span><br><span class="line">        ]</span><br><span class="line">        <span class="comment">// Select database</span></span><br><span class="line">        $<span class="keyword">this</span>-&gt;db = $<span class="keyword">this</span>-&gt;connection-&gt;&#123;$config[<span class="string">'database'</span>]&#125;;</span><br><span class="line"></span><br><span class="line">        $<span class="keyword">this</span>-&gt;useDefaultPostProcessor();</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<h3 id="Laravel-分组获取最新记录"><a href="#Laravel-分组获取最新记录" class="headerlink" title="Laravel 分组获取最新记录"></a>Laravel 分组获取最新记录</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">///https://learnku.com/articles/20626</span></span><br><span class="line">select * <span class="keyword">from</span> (select * <span class="keyword">from</span> project where user_id = :user_id order by id desc) <span class="keyword">as</span> a group by a.name order by id desc;</span><br><span class="line">select * <span class="keyword">from</span> (select * <span class="keyword">from</span> project where user_id = :user_id order by id desc limit <span class="number">10000</span>) <span class="keyword">as</span> a group by a.name order by id desc;</span><br><span class="line">public <span class="function"><span class="keyword">function</span> <span class="title">projectList</span>(<span class="params">Request $request</span>)</span>&#123;</span><br><span class="line">        $limit = $request-&gt;get(<span class="string">'limit'</span>,<span class="number">10</span>);</span><br><span class="line">        $user_id = $request-&gt;get(<span class="string">'user_id'</span>,<span class="literal">null</span>);</span><br><span class="line"></span><br><span class="line">        $sub_query = Project::where(<span class="string">'user_id'</span>,$user_id)-&gt;orderBy(<span class="string">'id'</span>,<span class="string">'desc'</span>)-&gt;limit(<span class="number">1000</span>);<span class="comment">//子查询</span></span><br><span class="line"></span><br><span class="line">        $results = Project::select(<span class="string">'*'</span>)</span><br><span class="line">                -&gt;<span class="keyword">from</span>(DB::raw(<span class="string">'('</span>.$sub_query-&gt;toSql().<span class="string">') as a'</span>)) <span class="comment">//from() 类似与 DB::table(), toSql()得到带 ? 号的执行 sql 语句</span></span><br><span class="line">                -&gt;mergeBindings($sub_query-&gt;getQuery())<span class="comment">//mergeBindings() 合并绑定参数,getQuery()获得具体值</span></span><br><span class="line">                -&gt;groupBy(<span class="string">'name'</span>)</span><br><span class="line">                -&gt;orderBy(<span class="string">'id'</span>,<span class="string">'desc'</span>)</span><br><span class="line">                -&gt;paginate($limit);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> $<span class="keyword">this</span>-&gt;pageDate($results);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<h3 id="将分组无结果的记录显示为0"><a href="#将分组无结果的记录显示为0" class="headerlink" title="将分组无结果的记录显示为0"></a>将分组无结果的记录显示为0</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">http:<span class="comment">//hshine.net/article/12 </span></span><br><span class="line">SELECT</span><br><span class="line">    ISNULL( SUM ( u_table1917.field5 ), <span class="number">0</span> ) As val,</span><br><span class="line">    u_table1916.companycode </span><br><span class="line">FROM</span><br><span class="line">    u_table1917</span><br><span class="line">    JOIN u_table1916 ON u_table1917.field3= u_table1916.field6 </span><br><span class="line">WHERE</span><br><span class="line">    u_table1916.field3 LIKE <span class="string">'2018%'</span> </span><br><span class="line">    AND u_table1916.companycode IN ( <span class="string">'GY00051'</span>, <span class="string">'GY00071'</span>, <span class="string">'GY00072'</span>, <span class="string">'GY00073'</span> ) </span><br><span class="line">GROUP BY</span><br><span class="line">    u_table1916.companycode</span><br><span class="line">    </span><br><span class="line">    SELECT DISTINCT Ma.companycode,ISNULL(Sub.val,<span class="number">0</span>) FROM --此处使用ISNULL对结果进行判空处理 </span><br><span class="line">    (</span><br><span class="line">    SELECT</span><br><span class="line">        u_table1916.companycode </span><br><span class="line">    FROM</span><br><span class="line">        u_table1917</span><br><span class="line">        JOIN u_table1916 ON u_table1917.field3= u_table1916.field6</span><br><span class="line">    --此处使用LEFT JOIN 关联，因为左表是包括所有数据记录的，而右表只包括符合条件的，这样就能获得</span><br><span class="line">    --将所有的结果来进行分组，再加上ISNULL的处理，就可以显示聚合为<span class="number">0</span>的记录</span><br><span class="line">    ) AS Ma LEFT JOIN </span><br><span class="line">    (</span><br><span class="line">    SELECT</span><br><span class="line">        SUM ( u_table1917.field5 ) As val,</span><br><span class="line">        u_table1916.companycode </span><br><span class="line">    FROM</span><br><span class="line">        u_table1917</span><br><span class="line">        JOIN u_table1916 ON u_table1917.field3= u_table1916.field6 </span><br><span class="line">    WHERE</span><br><span class="line">        u_table1916.field3 LIKE <span class="string">'2018%'</span> </span><br><span class="line">    GROUP BY</span><br><span class="line">        u_table1916.companycode</span><br><span class="line">    ) AS Sub ON Ma.companycode=Sub.companycode</span><br></pre></td></tr></table></figure>
<h3 id="MISCONF-Redis-is-configured-to-save-RDB-snapshots"><a href="#MISCONF-Redis-is-configured-to-save-RDB-snapshots" class="headerlink" title="MISCONF Redis is configured to save RDB snapshots"></a>MISCONF Redis is configured to save RDB snapshots</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">使用redis-cli，你可以这样做：</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line">CONFIG SET dir /tmp/some/directory/other/than/<span class="keyword">var</span></span><br><span class="line">CONFIG SET dbfilename temp.rdb</span><br><span class="line">千万不要使用https:<span class="comment">//blog.yiranzai.cn/posts/901/</span></span><br><span class="line"></span><br><span class="line"> </span><br><span class="line">config set stop-writes-on-bgsave-error no</span><br><span class="line">忽视这些错误并不是解决问题的办法。</span><br><span class="line"></span><br><span class="line">我的解决方案是</span><br><span class="line"></span><br><span class="line">修改配置文件，重启服务</span><br><span class="line"> </span><br><span class="line">$ mkdir /usr/local/redis/db</span><br><span class="line">$ vim redis.conf</span><br><span class="line"># 第263行左右  设置快照文件目录，切勿设置成一个redis用户没有权限的目录</span><br><span class="line">dir /usr/local/redis/db/</span><br><span class="line">$ chown -R redis:redis /usr/local/redis</span><br></pre></td></tr></table></figure>
<h3 id="MySQL数据库主从复制"><a href="#MySQL数据库主从复制" class="headerlink" title="MySQL数据库主从复制"></a>MySQL数据库主从复制</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line">$ systemctl start mysqld.service</span><br><span class="line">$ firewall-cmd --zone=public --add-port=<span class="number">80</span>/tcp --permanent</span><br><span class="line">$ firewall-cmd --reload</span><br><span class="line">master服务器配置：https:<span class="comment">//blog.yiranzai.cn/posts/5420/</span></span><br><span class="line">$ vim /etc/my.cnf</span><br><span class="line">[mysqld]</span><br><span class="line">server-id=<span class="number">1</span></span><br><span class="line">log-bin=mysql-bin # 启用二进制日志</span><br><span class="line"></span><br><span class="line">slave服务器配置：</span><br><span class="line">$ vim /etc/my.cnf</span><br><span class="line">[mysqld]</span><br><span class="line">log_bin           = mysql-bin</span><br><span class="line">server_id         = <span class="number">2</span></span><br><span class="line">relay_log         = mysql-relay-bin</span><br><span class="line">log_slave_updates = <span class="number">1</span></span><br><span class="line">read_only         = <span class="number">1</span></span><br><span class="line">slave-skip-errors = all   #忽略因复制出现的所有错误</span><br><span class="line"></span><br><span class="line">systemctl restart mysqld.service</span><br><span class="line">mysql&gt; MySQL -u root -p</span><br><span class="line">mysql&gt; GRANT REPLICATION SLAVE ON *.* to <span class="string">'user'</span>@<span class="string">'192.168.0.124'</span> identified by <span class="string">'password'</span>;</span><br><span class="line">mysql&gt; FLUSH PRIVILEGES;</span><br><span class="line">mysql&gt; FLUSH TABLES WITH READ LOCK;</span><br><span class="line">mysql&gt; show master status;</span><br><span class="line">mysql&gt; UNLOCK TABLES;</span><br><span class="line"></span><br><span class="line">mysql&gt; show maser status;</span><br><span class="line">+------------------+----------+--------------+------------------+-------------------+</span><br><span class="line">| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |</span><br><span class="line">+------------------+----------+--------------+------------------+-------------------+</span><br><span class="line">| mysql-bin<span class="number">.000004</span> |    <span class="number">24364</span> |              |                  |                   |</span><br><span class="line">+------------------+----------+--------------+------------------+-------------------+</span><br><span class="line"><span class="number">1</span> row <span class="keyword">in</span> set (<span class="number">0.02</span> sec)</span><br><span class="line">mysql&gt; change master to</span><br><span class="line"> -&gt; master_host=<span class="string">'192.168.0.123'</span>,</span><br><span class="line"> -&gt; master_user=<span class="string">'user'</span>,</span><br><span class="line"> -&gt; master_password=<span class="string">'password'</span>,</span><br><span class="line"> -&gt; master_log_file=<span class="string">'mysql-bin.000004'</span>,</span><br><span class="line"> -&gt; master_log_pos=<span class="number">24364</span>;</span><br><span class="line"></span><br><span class="line">mysql&gt; start slave;</span><br><span class="line">mysql&gt; show slave status \G;</span><br><span class="line">*************************** <span class="number">1.</span> row ***************************</span><br><span class="line">               Slave_IO_State: Waiting <span class="keyword">for</span> master to send event</span><br><span class="line">                  Master_Host: <span class="number">192.169</span><span class="number">.0</span><span class="number">.123</span></span><br><span class="line">                  Master_User: user</span><br><span class="line">                  Master_Port: <span class="number">3306</span></span><br><span class="line">                Connect_Retry: <span class="number">60</span></span><br><span class="line">              Master_Log_File: mysql-bin<span class="number">.000004</span></span><br><span class="line">          Read_Master_Log_Pos: <span class="number">24364</span></span><br><span class="line">               Relay_Log_File: mysql-relay-bin<span class="number">.000292</span></span><br><span class="line">                Relay_Log_Pos: <span class="number">283</span></span><br><span class="line">        Relay_Master_Log_File: mysql-bin<span class="number">.000004</span></span><br><span class="line">             Slave_IO_Running: Yes</span><br><span class="line">            Slave_SQL_Running: Yes</span><br><span class="line">...</span><br></pre></td></tr></table></figure>
<h3 id="Redis-快速实现签到统计"><a href="#Redis-快速实现签到统计" class="headerlink" title="Redis 快速实现签到统计"></a>Redis 快速实现签到统计</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">https:<span class="comment">//learnku.com/articles/25181</span></span><br><span class="line">在你想要的位置操作字节值，比如说用户 <span class="number">3</span> 在 <span class="number">3</span>月<span class="number">13</span>号 签到了，那么 setbit(<span class="number">20190313</span>, <span class="number">3</span> ,<span class="number">1</span>) 就可以实现签到功能了，这里的 offset 就是<span class="number">3</span></span><br><span class="line"> $dayKey = <span class="string">'login:'</span>.\date(<span class="string">'Ymd'</span>,\time());</span><br><span class="line">$redis-&gt;bitop(<span class="string">'AND'</span>, <span class="string">'threeAnd'</span>, <span class="string">'login:20190311'</span>, <span class="string">'login:20190312'</span>, <span class="string">'login:20190313'</span>);</span><br><span class="line">echo <span class="string">"连续三天都签到的用户数量："</span> . $redis-&gt;bitCount(<span class="string">'threeAnd'</span>);</span><br><span class="line"></span><br><span class="line">$redis-&gt;bitop(<span class="string">'OR'</span>, <span class="string">'threeOr'</span>, <span class="string">'login:20190311'</span>, <span class="string">'login:20190312'</span>, <span class="string">'login:20190313'</span>);</span><br><span class="line">echo <span class="string">"三天中签到用户数量（有一天签也算签了）："</span> . $redis-&gt;bitCount(<span class="string">'threeOr'</span>);</span><br><span class="line"></span><br><span class="line">$redis-&gt;bitop(<span class="string">'AND'</span>, <span class="string">'monthActivities'</span><span class="string">', $redis-&gt;keys('</span>login:<span class="number">201903</span>*<span class="string">'));</span></span><br><span class="line"><span class="string">echo "连续一个月签到用户数量：" . $redis-&gt;bitCount('</span>monthActivities<span class="string">');</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">echo "当前用户指定天数是否签到：" . $redis-&gt;getbit('</span>login:<span class="number">20190311</span><span class="string">', $this-&gt;user-&gt;id);</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL分组查询TOP-N的实践和踩坑"><a href="#MySQL分组查询TOP-N的实践和踩坑" class="headerlink" title="MySQL分组查询TOP N的实践和踩坑"></a>MySQL分组查询TOP N的实践和踩坑</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">https:<span class="comment">//blog.yiranzai.cn/posts/991/ 三个字段 课程 学生 成绩，如何取每门课程成绩 top3 的学生</span></span><br><span class="line">CREATE TABLE <span class="string">`test2`</span> (</span><br><span class="line">  <span class="string">`id`</span> int(<span class="number">11</span>) NOT NULL AUTO_INCREMENT,</span><br><span class="line">  <span class="string">`name`</span> varchar(<span class="number">20</span>) DEFAULT NULL,</span><br><span class="line">  <span class="string">`course`</span> varchar(<span class="number">20</span>) DEFAULT NULL,</span><br><span class="line">  <span class="string">`score`</span> int(<span class="number">11</span>) DEFAULT NULL,</span><br><span class="line">  PRIMARY KEY (<span class="string">`id`</span>),</span><br><span class="line">  KEY <span class="string">`course`</span> (<span class="string">`course`</span>,<span class="string">`score`</span>) USING BTREE</span><br><span class="line">) ENGINE=InnoDB AUTO_INCREMENT=<span class="number">1</span> DEFAULT CHARSET=utf8mb4;</span><br><span class="line">ysql&gt; INSERT INTO <span class="string">`test2`</span>(name,course,score) VALUES</span><br><span class="line">(<span class="string">'a1'</span>, <span class="string">'a'</span>, <span class="number">50</span>),</span><br><span class="line">(<span class="string">'a2'</span>, <span class="string">'a'</span>, <span class="number">50</span>),</span><br><span class="line">(<span class="string">'a3'</span>, <span class="string">'a'</span>, <span class="number">50</span>),</span><br><span class="line">(<span class="string">'a4'</span>, <span class="string">'a'</span>, <span class="number">40</span>),</span><br><span class="line">(<span class="string">'a5'</span>, <span class="string">'a'</span>, <span class="number">40</span>),</span><br><span class="line">(<span class="string">'a6'</span>, <span class="string">'a'</span>, <span class="number">40</span>),</span><br><span class="line">(<span class="string">'a7'</span>, <span class="string">'a'</span>, <span class="number">30</span>),</span><br><span class="line">(<span class="string">'a8'</span>, <span class="string">'a'</span>, <span class="number">30</span>),</span><br><span class="line">(<span class="string">'a9'</span>, <span class="string">'a'</span>, <span class="number">30</span>);</span><br><span class="line">mysql&gt; select * <span class="keyword">from</span> test2;</span><br><span class="line">+----+------+--------+-------+</span><br><span class="line">| id | name | course | score |</span><br><span class="line">+----+------+--------+-------+</span><br><span class="line">|  <span class="number">1</span> | a1   | a      |    <span class="number">50</span> |</span><br><span class="line">|  <span class="number">2</span> | a2   | a      |    <span class="number">50</span> |</span><br><span class="line">|  <span class="number">3</span> | a3   | a      |    <span class="number">50</span> |</span><br><span class="line">|  <span class="number">4</span> | a4   | a      |    <span class="number">40</span> |</span><br><span class="line">|  <span class="number">5</span> | a5   | a      |    <span class="number">40</span> |</span><br><span class="line">|  <span class="number">6</span> | a6   | a      |    <span class="number">40</span> |</span><br><span class="line">|  <span class="number">7</span> | a7   | a      |    <span class="number">30</span> |</span><br><span class="line">|  <span class="number">8</span> | a8   | a      |    <span class="number">30</span> |</span><br><span class="line">|  <span class="number">9</span> | a9   | a      |    <span class="number">30</span> |</span><br><span class="line">+----+------+--------+-------+</span><br><span class="line"><span class="number">9</span> rows <span class="keyword">in</span> set (<span class="number">0.06</span> sec)</span><br><span class="line">select *</span><br><span class="line"><span class="keyword">from</span> test1 a</span><br><span class="line">where <span class="number">3</span>&gt;(select count(*) <span class="keyword">from</span> test1 where course=a.course and score&gt;a.score)</span><br><span class="line">order by a.course,a.score desc;</span><br></pre></td></tr></table></figure>
<h3 id="case-when"><a href="#case-when" class="headerlink" title="case when"></a>case when</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">SELECT</span><br><span class="line">    CASE</span><br><span class="line">    WHEN user_sleep_time &lt;= <span class="number">1536595176</span></span><br><span class="line">        AND user_sleep_time &gt; <span class="number">1535212776</span> THEN</span><br><span class="line">    <span class="string">'twoWeekdsAgo'</span></span><br><span class="line">    WHEN user_sleep_time &lt;= <span class="number">1535212776</span></span><br><span class="line">        AND user_sleep_time &gt; <span class="number">1532620776</span> THEN</span><br><span class="line">    <span class="string">'thirtyDaysAgo'</span></span><br><span class="line">    WHEN user_sleep_time &lt;= <span class="number">1532620776</span></span><br><span class="line">        AND user_sleep_time &gt; <span class="number">1530028776</span> THEN</span><br><span class="line">    <span class="string">'sixtyDaysAgo'</span></span><br><span class="line">    WHEN user_sleep_time &lt;= <span class="number">1530028776</span></span><br><span class="line">        AND user_sleep_time &gt; <span class="number">1527436776</span> THEN</span><br><span class="line">    <span class="string">'ninetyDaysAgo'</span></span><br><span class="line">    WHEN user_sleep_time &lt;= <span class="number">1527436776</span></span><br><span class="line">        AND user_sleep_time &gt; <span class="number">1524844776</span> THEN</span><br><span class="line">    <span class="string">'oneHundredAndTwentyDaysAgo'</span></span><br><span class="line">    WHEN user_sleep_time &lt;= <span class="number">1524844776</span></span><br><span class="line">        AND user_sleep_time &gt; <span class="number">1522252776</span> THEN</span><br><span class="line">    <span class="string">'oneHundredAndFiftyDaysAgo'</span></span><br><span class="line">    WHEN user_sleep_time &lt;= <span class="number">1522252776</span> THEN</span><br><span class="line">    <span class="string">'oneHundredAndEightyDaysAgo'</span></span><br><span class="line">    ELSE <span class="number">0</span></span><br><span class="line">    END sleep, COUNT(*) AS userCount</span><br><span class="line">FROM <span class="string">`user_sleep_relation`</span></span><br><span class="line">WHERE <span class="string">`user_recall_time`</span> &lt; <span class="number">1536595176</span></span><br><span class="line">GROUP BY  <span class="string">`sleep`</span>  </span><br><span class="line">https:<span class="comment">//learnku.com/articles/17547</span></span><br></pre></td></tr></table></figure>
<h3 id="mysql-replace-into-坑"><a href="#mysql-replace-into-坑" class="headerlink" title="mysql replace into 坑"></a>mysql replace into 坑</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">replace into执行的逻辑</span><br><span class="line"><span class="number">1</span>、遇到PRIMARY KEY或UNIQUE索引的，新记录与旧记录有冲突的（这里实际产生了异常duplicate key error），会把旧记录删除，然后再插入新记录</span><br><span class="line"><span class="number">2</span>、若是新记录没有冲突，就直接插入一条新记录，与insert into一样</span><br><span class="line"> </span><br><span class="line">看起来很正常，这里针对第一种逻辑会有问题https:<span class="comment">//jjhpeopl.iteye.com/blog/2368927  https://blog.xupeng.me/2013/10/11/mysql-replace-into-trap/</span></span><br><span class="line"><span class="number">1</span>、把旧记录删除之后，插入的新记录只是插入了那些指定的字段，原本不想更新的字段，直接为默认值了，会导致数据丢失</span><br><span class="line"><span class="number">2</span>、若旧记录的id跟其他表是有关联的，更新后新记录会产生新的id，导致这种关联丢失</span><br><span class="line"><span class="number">3</span>、而且使用replace into会导致自增主键id一直增大，很容易导致id值范围不够用</span><br><span class="line">另外，若是数据库存在主从关系，在主机器上进行了replace into操作之后，从机器上对应表的AUTO_INCREMENT是不会更新的，导致从机器转为主机器时，新插入数据会出现异常，直到AUTO_INCREMENT增加到原来主机器的值为止。 </span><br><span class="line">CREATE TABLE <span class="string">`auto`</span> (</span><br><span class="line">  <span class="string">`id`</span> int(<span class="number">10</span>) unsigned NOT NULL AUTO_INCREMENT,</span><br><span class="line">  <span class="string">`k`</span> int(<span class="number">10</span>) unsigned NOT NULL,</span><br><span class="line">  <span class="string">`v`</span> varchar(<span class="number">100</span>) DEFAULT NULL,</span><br><span class="line">  <span class="string">`extra`</span> varchar(<span class="number">200</span>) DEFAULT NULL,</span><br><span class="line">  PRIMARY KEY (<span class="string">`id`</span>),</span><br><span class="line">  UNIQUE KEY <span class="string">`uk_k`</span> (<span class="string">`k`</span>)</span><br><span class="line">) ENGINE=InnoDB DEFAULT CHARSET=latin1</span><br><span class="line">INSERT INTO auto (k, v, extra) VALUES (<span class="number">1</span>, <span class="string">'1'</span>, <span class="string">'extra 1'</span>), (<span class="number">2</span>, <span class="string">'2'</span>, <span class="string">'extra 2'</span>), (<span class="number">3</span>, <span class="string">'3'</span>, <span class="string">'extra 3'</span>);</span><br><span class="line">Query OK, <span class="number">3</span> rows affected (<span class="number">0.01</span> sec)</span><br><span class="line">Records: <span class="number">3</span>  Duplicates: <span class="number">0</span>  Warnings: <span class="number">0</span></span><br><span class="line"></span><br><span class="line">xupeng@diggle7:<span class="number">3600</span>(dba_m) [dba] mysql&gt; SHOW CREATE TABLE auto\G</span><br><span class="line">*************************** <span class="number">1.</span> row ***************************</span><br><span class="line">       Table: auto</span><br><span class="line">Create Table: CREATE TABLE <span class="string">`auto`</span> (</span><br><span class="line">  <span class="string">`id`</span> int(<span class="number">10</span>) unsigned NOT NULL AUTO_INCREMENT,</span><br><span class="line">  <span class="string">`k`</span> int(<span class="number">10</span>) unsigned NOT NULL,</span><br><span class="line">  <span class="string">`v`</span> varchar(<span class="number">100</span>) DEFAULT NULL,</span><br><span class="line">  <span class="string">`extra`</span> varchar(<span class="number">200</span>) DEFAULT NULL,</span><br><span class="line">  PRIMARY KEY (<span class="string">`id`</span>),</span><br><span class="line">  UNIQUE KEY <span class="string">`uk_k`</span> (<span class="string">`k`</span>)</span><br><span class="line">) ENGINE=InnoDB AUTO_INCREMENT=<span class="number">4</span> DEFAULT CHARSET=latin1</span><br><span class="line"><span class="number">1</span> row <span class="keyword">in</span> set (<span class="number">0.01</span> sec)</span><br><span class="line"></span><br><span class="line">xupeng@diggle7:<span class="number">3600</span>(dba_m) [dba] mysql&gt; SELECT * FROM auto;</span><br><span class="line">+----+---+------+---------+</span><br><span class="line">| id | k | v    | extra   |</span><br><span class="line">+----+---+------+---------+</span><br><span class="line">|  <span class="number">1</span> | <span class="number">1</span> | <span class="number">1</span>    | extra <span class="number">1</span> |</span><br><span class="line">|  <span class="number">2</span> | <span class="number">2</span> | <span class="number">2</span>    | extra <span class="number">2</span> |</span><br><span class="line">|  <span class="number">3</span> | <span class="number">3</span> | <span class="number">3</span>    | extra <span class="number">3</span> |</span><br><span class="line">+----+---+------+---------+</span><br><span class="line"><span class="number">3</span> rows <span class="keyword">in</span> set (<span class="number">0.00</span> sec)</span><br><span class="line">REPLACE INTO auto (k, v) VALUES (<span class="number">1</span>, <span class="string">'1-1'</span>);</span><br><span class="line">SELECT * FROM auto;</span><br><span class="line">+----+---+------+---------+</span><br><span class="line">| id | k | v    | extra   |</span><br><span class="line">+----+---+------+---------+</span><br><span class="line">|  <span class="number">2</span> | <span class="number">2</span> | <span class="number">2</span>    | extra <span class="number">2</span> |</span><br><span class="line">|  <span class="number">3</span> | <span class="number">3</span> | <span class="number">3</span>    | extra <span class="number">3</span> |</span><br><span class="line">|  <span class="number">4</span> | <span class="number">1</span> | <span class="number">1</span><span class="number">-1</span>  | NULL    |</span><br><span class="line">+----+---+------+---------+</span><br><span class="line"><span class="number">3</span> rows <span class="keyword">in</span> set (<span class="number">0.00</span> sec)</span><br><span class="line">执行完 REPLACE INTO auto (k, v) VALUES (<span class="number">1</span>, ‘<span class="number">1</span><span class="number">-1</span>’) 之后，由于新写入记录时并未给 extra 字段指定值，原记录 extra 字段的值就「丢失」了，而通常这并非是业务上所预期的，更常见的需求实际上是，当存在 k=<span class="number">1</span> 的记录时，就把 v 字段的值更新为 ‘<span class="number">1</span><span class="number">-1</span>’，其他未指定的字段则保持原状，而满足这一需求的 MySQL 方言是 INSERT INTO auto (k, v) VALUES (<span class="number">1</span>, ‘<span class="number">1</span><span class="number">-1</span>’) ON DUPLICATE KEY UPDATE v=VALUES(v);</span><br><span class="line"></span><br><span class="line">鉴于此，很多使用 REPLACE INTO 的场景，实际上需要的是 INSERT INTO … ON DUPLICATE KEY UPDATE，在正确理解 REPLACE INTO 行为和副作用的前提下，谨慎使用 REPLACE INTO。</span><br></pre></td></tr></table></figure>
<h3 id="类型转换对-MySQL-选择索引的影响"><a href="#类型转换对-MySQL-选择索引的影响" class="headerlink" title="类型转换对 MySQL 选择索引的影响"></a>类型转换对 MySQL 选择索引的影响</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line">mysql [localhost] &#123;msandbox&#125; (test) &gt; explain select age <span class="keyword">from</span></span><br><span class="line">    -&gt; indextest where name=<span class="number">111222</span>\G</span><br><span class="line">*************************** <span class="number">1.</span> row ***************************</span><br><span class="line">           id: <span class="number">1</span></span><br><span class="line">  select_type: SIMPLE</span><br><span class="line">        table: indextest</span><br><span class="line">         type: ALL</span><br><span class="line">possible_keys: idx_name</span><br><span class="line">          key: NULL</span><br><span class="line">      key_len: NULL</span><br><span class="line">          ref: NULL</span><br><span class="line">         rows: <span class="number">4</span></span><br><span class="line">        Extra: Using where</span><br><span class="line"><span class="number">1</span> row <span class="keyword">in</span> set (<span class="number">0.00</span> sec)</span><br><span class="line">https:<span class="comment">//blog.xupeng.me/2012/02/08/type-conversion-and-index-selection-of-mysql/</span></span><br><span class="line">mysql [localhost] &#123;msandbox&#125; (test) &gt; SELECT <span class="string">'18015376320243459'</span> =</span><br><span class="line">    -&gt; <span class="number">18015376320243459</span>;</span><br><span class="line">+-----------------------------------------+</span><br><span class="line">| <span class="string">'18015376320243459'</span> = <span class="number">18015376320243459</span> |</span><br><span class="line">+-----------------------------------------+</span><br><span class="line">|                                       <span class="number">0</span> |</span><br><span class="line">+-----------------------------------------+</span><br><span class="line"><span class="number">1</span> row <span class="keyword">in</span> set (<span class="number">0.00</span> sec)</span><br><span class="line"></span><br><span class="line">mysql [localhost] &#123;msandbox&#125; (test) &gt; SELECT <span class="string">'18015376320243459'</span> + <span class="number">0</span>;</span><br><span class="line">+-------------------------+</span><br><span class="line">| <span class="string">'18015376320243459'</span> + <span class="number">0</span> |</span><br><span class="line">+-------------------------+</span><br><span class="line">|    <span class="number">1.80153763202435e+16</span> |</span><br><span class="line">+-------------------------+</span><br><span class="line"><span class="number">1</span> row <span class="keyword">in</span> set (<span class="number">0.00</span> sec)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">mysql [localhost] &#123;msandbox&#125; (test) &gt; SELECT</span><br><span class="line">    -&gt; cast(<span class="string">'18015376320243459'</span> <span class="keyword">as</span> unsigned) =  <span class="number">18015376320243459</span>;</span><br><span class="line">+-----------------------------------------------------------+</span><br><span class="line">| cast(<span class="string">'18015376320243459'</span> <span class="keyword">as</span> unsigned) = <span class="number">18015376320243459</span> |</span><br><span class="line">+-----------------------------------------------------------+</span><br><span class="line">|                                                         <span class="number">1</span> |</span><br><span class="line">+-----------------------------------------------------------+</span><br><span class="line"><span class="number">1</span> row <span class="keyword">in</span> set (<span class="number">0.00</span> sec)</span><br><span class="line">因为浮点数精度(<span class="number">53</span> bits)问题，并且 MySQL 将字符串转换为浮点数和将整数转换为浮点数使用不同的方法，字符串 <span class="string">'18015376320243459'</span> 和整数 <span class="number">18015376320243459</span> 相比较就不相等，如果要避免隐式浮点数转换带来的精度问题，可以显式地使用 cast 做类型转换，将字符串转换为整数。</span><br><span class="line"></span><br><span class="line">按照这些规则，对于上面的例子来说，name 字段的值和查询参数 <span class="string">'111222'</span> 都会被转换为浮点数才会做比较，而很多文本都能转换为和 <span class="number">111222</span> 相等的数值，比如 <span class="string">'111222'</span>, <span class="string">'111222aabb'</span>, <span class="string">' 111222'</span> 和 <span class="string">'11122.2e1'</span>，所以 MySQL 不能有效使用索引，就退化为索引扫描甚至是全表扫描。</span><br><span class="line">反过来，如果使用一个字符串作为查询参数，对一个数字字段做比较查询，MySQL 则是可以有效利用索引的</span><br><span class="line">MySQL 可以将查询参数 <span class="string">'30'</span> 转换为确定的数值 <span class="number">30</span>，之后可以快速地在索引中找到与之相等的数值</span><br><span class="line"></span><br><span class="line"> explain select * <span class="keyword">from</span></span><br><span class="line">    -&gt; indextest where date(create_time)=<span class="string">'2012-02-02'</span>\G</span><br><span class="line">explain select * <span class="keyword">from</span></span><br><span class="line">    -&gt; indextest where create_time between <span class="string">'2012-02-02'</span> and <span class="string">'2012-02-03'</span>\G</span><br></pre></td></tr></table></figure>
<h3 id="redis-keys-scan"><a href="#redis-keys-scan" class="headerlink" title="redis keys scan"></a>redis keys scan</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">$redis-&gt;keys(<span class="string">'login:201903*'</span>)</span><br><span class="line">$redis-&gt;bitop(<span class="string">'AND'</span>,  <span class="string">'monthActivities'</span><span class="string">', $redis-&gt;keys('</span>login:<span class="number">201903</span>*<span class="string">'));</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">echo "连续一个月签到用户数量：" . $redis-&gt;bitCount('</span>monthActivities<span class="string">');https://learnku.com/articles/25892</span></span><br><span class="line"><span class="string">当前的 keys 指令执行完了才可以继续，再加上 keys 操作是遍历算法，复杂度是 O(n)，乍一想就知道问题所在了，当实例中数据量过大的时候，Redis 服务可能会卡顿，其余指令可能会延时甚至超时报错..</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">127.0.0.1:6379&gt; setbit login:20190321 1 1</span></span><br><span class="line"><span class="string">(integer) 0</span></span><br><span class="line"><span class="string">127.0.0.1:6379&gt; setbit login:20190321 2 1</span></span><br><span class="line"><span class="string">(integer) 0</span></span><br><span class="line"><span class="string">127.0.0.1:6379&gt; setbit login:20190322 2 1</span></span><br><span class="line"><span class="string">(integer) 0</span></span><br><span class="line"><span class="string">127.0.0.1:6379&gt; setbit login:20190323 2 1</span></span><br><span class="line"><span class="string">(integer) 0</span></span><br><span class="line"><span class="string">127.0.0.1:6379&gt; keys login:201903*</span></span><br><span class="line"><span class="string">1) "login:20190323"</span></span><br><span class="line"><span class="string">2) "login:20190322"</span></span><br><span class="line"><span class="string">3) "login:20190321"</span></span><br><span class="line"><span class="string">127.0.0.1:6379&gt; scan 0 match login:201903*</span></span><br><span class="line"><span class="string">1) "3"</span></span><br><span class="line"><span class="string">2) 1) "login:20190323"</span></span><br><span class="line"><span class="string">   2) "login:20190322"</span></span><br><span class="line"><span class="string">127.0.0.1:6379&gt; scan 0 match login:201903* count 2</span></span><br><span class="line"><span class="string">1) "4"</span></span><br><span class="line"><span class="string">2) (empty list or set)</span></span><br><span class="line"><span class="string">127.0.0.1:6379&gt; scan 0 match login:201903* count 20</span></span><br><span class="line"><span class="string">1) "0"</span></span><br><span class="line"><span class="string">2) 1) "login:20190323"</span></span><br><span class="line"><span class="string">   2) "login:20190322"</span></span><br><span class="line"><span class="string">   3) "login:20190321"</span></span><br></pre></td></tr></table></figure>
<h3 id="mysql5-7Incorrect-datetime-value-‘0000-00-00-00-00-00’-for-column"><a href="#mysql5-7Incorrect-datetime-value-‘0000-00-00-00-00-00’-for-column" class="headerlink" title="mysql5.7Incorrect datetime value: ‘0000-00-00 00:00:00’ for column"></a>mysql5.7Incorrect datetime value: ‘0000-00-00 00:00:00’ for column</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">`created_at`</span> timestamp NOT NULL DEFAULT <span class="string">'0000-00-00 00:00:00'</span>, </span><br><span class="line"><span class="string">`updated_at`</span> timestamp NOT NULL DEFAULT <span class="string">'0000-00-00 00:00:00'</span>,</span><br><span class="line">show variables like <span class="string">'sql_m%'</span>;</span><br><span class="line">sql_mode      | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION </span><br><span class="line"></span><br><span class="line">alter table test modify created_at datetime NOT NULL;</span><br><span class="line">alter table test modify updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;</span><br><span class="line"></span><br><span class="line"><span class="number">5.7</span> timestamp类型取值范围：<span class="number">1970</span><span class="number">-01</span><span class="number">-01</span> <span class="number">00</span>:<span class="number">00</span>:<span class="number">00</span> 到 <span class="number">2037</span><span class="number">-12</span><span class="number">-31</span> <span class="number">23</span>:<span class="number">59</span>:<span class="number">59</span>，初始值调整为 <span class="number">1970</span><span class="number">-01</span><span class="number">-02</span> <span class="number">00</span>:<span class="number">00</span>:<span class="number">00</span> 就可以了 </span><br><span class="line"></span><br><span class="line">alter table test modify created_at timestamp NOT NULL DEFAULT <span class="string">'1970-01-02 00:00:00'</span>;</span><br><span class="line">alter table test modify updated_at timestamp NOT NULL DEFAULT <span class="string">'1970-01-02 00:00:00'</span>;</span><br></pre></td></tr></table></figure>
<h3 id="mysql的limit进行分页时出现重复"><a href="#mysql的limit进行分页时出现重复" class="headerlink" title="mysql的limit进行分页时出现重复"></a>mysql的limit进行分页时出现重复</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">select * <span class="keyword">from</span> table order by xx limit <span class="number">0</span>,<span class="number">10</span></span><br><span class="line"></span><br><span class="line">当xx不存在索引，且有xx相同的行是，可能出现分页数据重复问题</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">解决办法：</span><br><span class="line">         <span class="number">1.</span>加上索引排序</span><br><span class="line">         select * <span class="keyword">from</span> table order by xx,id（任意有索引的字段） limit <span class="number">0</span>,<span class="number">10</span></span><br><span class="line">         <span class="number">2</span>、给xx字段加上索引</span><br><span class="line">         作为验证，您可以在这个字段上加索引  alter table tea_course_sort add index(course_sort_order)，然后由于这个表数目太小，以防加索引都未必能用得上，语句修改为</span><br><span class="line">       select * <span class="keyword">from</span> tea_course_sort  force index(course_sort_order) order by tea_course_sort.course_sort_order desc  limit <span class="number">0</span>,<span class="number">10</span>;</span><br><span class="line">来得到您预期的结果</span><br><span class="line"> </span><br><span class="line">select  * <span class="keyword">from</span> table_1 where <span class="number">1</span>=<span class="number">1</span> limit m,n</span><br><span class="line"></span><br><span class="line">这样后面的页可能会出现重复数据，这时可以通过加入order by 子句来解决这种情况， select * <span class="keyword">from</span> table_1  where <span class="number">1</span>=<span class="number">1</span> order by field_1 limit m,n</span><br><span class="line"></span><br><span class="line">但是这里需要特别注意，如果field_1字段有相同值的情况下，后面的页还是会出现重复数据，这时可以加入第二个排序字段（值唯一），可以选主键id,</span><br><span class="line"></span><br><span class="line">对应的sql语句是select * <span class="keyword">from</span> table_1  where <span class="number">1</span>=<span class="number">1</span> order by field_1 , id limit m,n</span><br><span class="line"></span><br><span class="line">但是最好保证field_1在表中的值是唯一的，这样就可以少写一个排序字段，增加查询效率，因为在只有一个排序字段的情况下，mysql会使用索引，如果是有多个排序字段的话，mysql会放弃索引做全表扫描。</span><br></pre></td></tr></table></figure>
<h3 id="预估-Mysql-数据表的数据大小和索引大小"><a href="#预估-Mysql-数据表的数据大小和索引大小" class="headerlink" title="预估 Mysql 数据表的数据大小和索引大小"></a>预估 Mysql 数据表的数据大小和索引大小</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">SELECT data_length,index_length</span><br><span class="line">FROM information_schema.TABLES t</span><br><span class="line">WHERE table_schema=<span class="string">'your_db_name'</span></span><br><span class="line">AND table_name = <span class="string">'your_table_name'</span>;</span><br><span class="line">直接查询 avg_row_length 字段，这个字段表示数据表的平均行大小，和上面自己计算的结果类似。</span><br><span class="line">SHOW COLUMNS FROM TABLES;</span><br><span class="line">https:<span class="comment">//www.playpi.org/2019041001.html</span></span><br></pre></td></tr></table></figure>
<h3 id="mysql-limit查询优化方法"><a href="#mysql-limit查询优化方法" class="headerlink" title="mysql limit查询优化方法"></a>mysql limit查询优化方法</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">对同一张表在不同的地方取<span class="number">10</span>条数据： <span class="number">1</span>）offset比较小时  </span><br><span class="line"> </span><br><span class="line">代码示例: select * <span class="keyword">from</span> user limit <span class="number">10</span>,<span class="number">10</span>;   这条sql语句多次运行，时间保持在<span class="number">0.0004</span><span class="number">-0.0005</span>之间。  </span><br><span class="line"> </span><br><span class="line">代码示例: select * <span class="keyword">from</span> user where uid &gt;=( select uid <span class="keyword">from</span> user order by uid limit <span class="number">10</span>,<span class="number">1</span> ) limit <span class="number">10</span>;   这条sql语句多次运行，时间保持在<span class="number">0.0005</span><span class="number">-0.0006</span>之间，主要是<span class="number">0.0006</span>。 结论：偏移offset较小时，直接使用limit较优。这个显然是子查询的原因。</span><br><span class="line"> </span><br><span class="line"><span class="number">2</span>）offset大时  </span><br><span class="line"> </span><br><span class="line">代码示例: select * <span class="keyword">from</span> user limit <span class="number">10000</span>,<span class="number">10</span>;   这条sql语句多次运行，时间保持在<span class="number">0.0187</span>左右  </span><br><span class="line"> </span><br><span class="line">代码示例: select * <span class="keyword">from</span> user where uid &gt;=( select uid <span class="keyword">from</span> user order by uid limit <span class="number">10000</span>,<span class="number">1</span> ) limit <span class="number">10</span>; 这条sql语句多次运行，时间保持在<span class="number">0.0061</span>左右，只有前者的<span class="number">1</span>/<span class="number">3</span>。可以预计offset越大，后者越优。</span><br><span class="line"> </span><br><span class="line">通过以上对比，得出mysql limit查询语句优化经验： 使用limit语句时，当数据量偏移量较小时可以直接使用limit，当数据量偏移量较大时，可以适当的使用子查询来做相关的性能优化。</span><br><span class="line">--------------------- </span><br><span class="line"> select * <span class="keyword">from</span> test a inner join (select id <span class="keyword">from</span> test where val=<span class="number">4</span> limit <span class="number">300000</span>,<span class="number">5</span>) b on a.id=b.id;</span><br></pre></td></tr></table></figure>
<h3 id="FOUND-ROWS"><a href="#FOUND-ROWS" class="headerlink" title="FOUND_ROWS()"></a>FOUND_ROWS()</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">分页程序一般由两条SQL组成：</span><br><span class="line">SELECT COUNT(*) FROM ... WHERE ....</span><br><span class="line">SELECT ... FROM ... WHERE LIMIT ...</span><br><span class="line"></span><br><span class="line">如果使用SQL_CALC_FOUND_ROWS的话，一条SQL就可以了：</span><br><span class="line">SELECT SQL_CALC_FOUND_ROWS ... FROM ... WHERE LIMIT ...</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line">当我们在处理分页程序的时候，会使用 limit 来限制返回的数量，然后会有两种获取分页的方法：</span><br><span class="line"></span><br><span class="line">第一种方法：</span><br><span class="line"></span><br><span class="line">在 SELECT 语句中加入 SQL_CALC_FOUND_ROWS 选项，然后通过 SELECT FOUND_ROWS() 来获取总行数：</span><br><span class="line"></span><br><span class="line">SELECT SQL_CALC_FOUND_ROWS * FROM table WHERE id &gt; <span class="number">100</span> LIMIT <span class="number">10</span>;</span><br><span class="line">SELECT FOUND_ROWS();</span><br><span class="line">第二种方式：</span><br><span class="line">使用正常的 SQL 语句，然后再用 SELECT COUNT(*) 来获取总行数：</span><br><span class="line"></span><br><span class="line">SELECT * FROM table WHERE id &gt; <span class="number">100</span> LIMIT <span class="number">10</span>;</span><br><span class="line">SELECT COUNT(*) FROM table WHERE id &gt; <span class="number">100</span>;</span><br><span class="line">经过测试，一般来说 SQL_CALC_FOUND_ROWS 是比较慢的，SQL执行的时间甚至会达到<span class="number">10</span>倍那么夸张，所以最好别使用 MySQL 的 SQL_CALC_FOUND_ROWS 来获取总行数</span><br></pre></td></tr></table></figure>
<h3 id="left-join-on-where"><a href="#left-join-on-where" class="headerlink" title="left join on where"></a>left join on where</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">使用了 left join，where 是针对左表，但左表是日期表，那如何做业务表上的条件限制</span><br><span class="line">数据库在通过连接两张或多张表来返回记录时，都会生成一张中间的临时表，然后再将这张临时表返回给用户；</span><br><span class="line"></span><br><span class="line">where 条件是在临时表生成好后，再对临时表进行过滤的条件；</span><br><span class="line"></span><br><span class="line">因此：where 条件加上，已经没有 left join 的含义（必须返回左边表的记录）了，条件不为真的就全部过滤掉。</span><br><span class="line"></span><br><span class="line">解决方案是把限制条件放在 on 后面</span><br><span class="line"></span><br><span class="line">select a.*,b.*</span><br><span class="line"><span class="keyword">from</span> table1 a</span><br><span class="line">left join table2 b on b.X=a.X and XXX</span><br><span class="line">结论：https:<span class="comment">//learnku.com/articles/26796 </span></span><br><span class="line"></span><br><span class="line">where 后面：是先连接然生成临时查询结果，然后再筛选</span><br><span class="line"></span><br><span class="line">on 后面：先根据条件过滤筛选，再连 生成临时查询结果</span><br></pre></td></tr></table></figure>
<h3 id="如何索引-JSON-字段"><a href="#如何索引-JSON-字段" class="headerlink" title="如何索引 JSON 字段"></a>如何索引 JSON 字段</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">CREATE TABLE <span class="string">`players`</span> (  </span><br><span class="line">   <span class="string">`id`</span> INT UNSIGNED NOT NULL,</span><br><span class="line">   <span class="string">`player_and_games`</span> <span class="built_in">JSON</span> NOT NULL,</span><br><span class="line">   <span class="string">`names_virtual`</span> VARCHAR(<span class="number">20</span>) GENERATED ALWAYS AS (<span class="string">`player_and_games`</span> -&gt;&gt; <span class="string">'$.name'</span>) NOT NULL, </span><br><span class="line">   PRIMARY KEY (<span class="string">`id`</span>)</span><br><span class="line">);</span><br><span class="line">SELECT * FROM <span class="string">`players`</span>;</span><br><span class="line">https:<span class="comment">//learnku.com/articles/27046#topnav</span></span><br><span class="line">+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+</span><br><span class="line">| id | player_and_games                                                                                                                                                                                           | names_virtual |</span><br><span class="line">+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+</span><br><span class="line">|  <span class="number">1</span> | &#123;<span class="string">"id"</span>: <span class="number">1</span>, <span class="string">"name"</span>: <span class="string">"Sally"</span>, <span class="string">"games_played"</span>: &#123;<span class="string">"Puzzler"</span>: &#123;<span class="string">"time"</span>: <span class="number">7</span>&#125;, <span class="string">"Battlefield"</span>: &#123;<span class="string">"rank"</span>: <span class="string">"Sergeant V"</span>, <span class="string">"level"</span>: <span class="number">20</span>, <span class="string">"weapon"</span>: <span class="string">"sniper rifle"</span>&#125;, <span class="string">"Crazy Tennis"</span>: &#123;<span class="string">"won"</span>: <span class="number">4</span>, <span class="string">"lost"</span>: <span class="number">1</span>&#125;&#125;&#125;                  | Sally         |</span><br><span class="line">|  <span class="number">2</span> | &#123;<span class="string">"id"</span>: <span class="number">2</span>, <span class="string">"name"</span>: <span class="string">"Thom"</span>, <span class="string">"games_played"</span>: &#123;<span class="string">"Puzzler"</span>: &#123;<span class="string">"time"</span>: <span class="number">25</span>&#125;, <span class="string">"Battlefield"</span>: &#123;<span class="string">"rank"</span>: <span class="string">"Major General VIII"</span>, <span class="string">"level"</span>: <span class="number">127</span>, <span class="string">"weapon"</span>: <span class="string">"carbine"</span>&#125;, <span class="string">"Crazy Tennis"</span>: &#123;<span class="string">"won"</span>: <span class="number">10</span>, <span class="string">"lost"</span>: <span class="number">30</span>&#125;&#125;&#125;            | Thom          |</span><br><span class="line">CREATE INDEX <span class="string">`names_idx`</span> ON <span class="string">`players`</span>(<span class="string">`names_virtual`</span>);  </span><br><span class="line"></span><br><span class="line">EXPLAIN SELECT * FROM <span class="string">`players`</span> WHERE <span class="string">`names_virtual`</span> = <span class="string">"Sally"</span>\G  </span><br><span class="line">*************************** <span class="number">1.</span> row ***************************</span><br><span class="line">           id: <span class="number">1</span></span><br><span class="line">  select_type: SIMPLE</span><br><span class="line">        table: players</span><br><span class="line">   partitions: NULL</span><br><span class="line">         type: ref</span><br><span class="line">possible_keys: names_idx  </span><br><span class="line">          key: names_idx</span><br><span class="line">      key_len: <span class="number">22</span></span><br><span class="line">          ref: <span class="keyword">const</span></span><br><span class="line">         rows: <span class="number">1</span></span><br><span class="line">     filtered: <span class="number">100.00</span></span><br><span class="line">        Extra: NULL</span><br></pre></td></tr></table></figure>
<h3 id="length-检测-vachar-字节长度"><a href="#length-检测-vachar-字节长度" class="headerlink" title="length 检测 vachar 字节长度"></a>length 检测 vachar 字节长度</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">insert into test value (<span class="number">1</span>, <span class="string">'测'</span>)</span><br><span class="line">SELECT id, LENGTH(str), CHAR_LENGTH(str) FROM test;返回结果是 <span class="number">1</span> <span class="number">3</span> <span class="number">1</span></span><br><span class="line">ALTER TABLE <span class="string">`test`</span></span><br><span class="line">ADD COLUMN <span class="string">`str2`</span>  varchar(<span class="number">2000</span>) NULL AFTER <span class="string">`str`</span>;</span><br><span class="line">SELECT id, LENGTH(str2), CHAR_LENGTH(str2) FROM test where id = <span class="number">2</span>;</span><br><span class="line">添加了一个 str2 字段，然后插入 <span class="number">256</span> 个汉字，返回结果是</span><br><span class="line"><span class="number">2</span> <span class="number">768</span> <span class="number">256</span></span><br><span class="line">mysql lenght 是字符串所占的字节，并没有计算额外的所需字节。https:<span class="comment">//learnku.com/laravel/t/27848</span></span><br></pre></td></tr></table></figure>
<h3 id="浅析乐观锁与悲观锁"><a href="#浅析乐观锁与悲观锁" class="headerlink" title="浅析乐观锁与悲观锁"></a>浅析乐观锁与悲观锁</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">使用悲观锁https:<span class="comment">//learnku.com/articles/27880</span></span><br><span class="line">悲观并发控制实际上是 “先取锁，再访问” 的保守策略，为数据处理的安全提供了保证。</span><br><span class="line">begin;</span><br><span class="line">select quantity <span class="keyword">from</span> products where id = <span class="number">1</span> <span class="keyword">for</span> update;</span><br><span class="line">update products set quanntity = <span class="number">2</span> where id = <span class="number">1</span>;</span><br><span class="line">commit;</span><br><span class="line">以上，对 id 为 <span class="number">1</span> 的产品进行修改，先通过 <span class="keyword">for</span> update 的方式进行加锁，然后再修改。典型的悲观锁策略。</span><br><span class="line">在对数据修改前，尝试增加排他锁。</span><br><span class="line">加锁失败，意味着数据正在被修改，进行等待或者抛出异常。</span><br><span class="line">加锁成功，对数据进行修改，提交事务，锁释放。</span><br><span class="line">如果我们加锁成功，有其他线程对该数据进操作或者加排他锁的操作，只能等待或者抛出异常。</span><br><span class="line"></span><br><span class="line">如果修改库存的逻辑发生并发，同一时间只有一个线程可以开启事务并获得 id = <span class="number">1</span> 的锁，其他事务必须等本次提交之后才能执行，这样可以保证数据不被其他事务修改。</span><br><span class="line"></span><br><span class="line">使用排他锁会把数据锁住，不过需要注意一些基本的锁级别，MySQL InnoDB 默认行级锁。行级锁是基于索引的，如果一条 SQL 语句用不到索引是不会使用行级锁，会使用表级锁把整张表锁住。</span><br><span class="line">使用乐观锁</span><br><span class="line"></span><br><span class="line">select quantity <span class="keyword">from</span> products where id = <span class="number">1</span></span><br><span class="line">update products set quantity = <span class="number">2</span> where id = <span class="number">1</span> and quantity = <span class="number">3</span></span><br><span class="line">先查询库存表当前库存数，然后更新的时候判断数据表对应数据的 quantity 与第一次取出来的是否一致，一致则更新，否则认为是过期数据。</span><br><span class="line"></span><br><span class="line">这样实现有一个问题，线程 <span class="number">1</span> 从数据库取出 quantity 为 <span class="number">3</span>，线程 <span class="number">2</span> 也取出同一条数据的 quantity，进行操作，变成了 <span class="number">2</span>，然后又进行某些操作 变成了 <span class="number">3</span>，此时线程 <span class="number">1</span> 进行更新操作成功。但是这个过程有问题。</span><br><span class="line"></span><br><span class="line">引入 version 参数，乐观锁每次在执行数据修改的操作，都会带上版本号，一旦版本号和数据的版本号一致就可以执行修改操作并对 version 执行 +<span class="number">1</span> 操作，否则就执行失败。</span><br><span class="line"></span><br><span class="line">这样实现也有一个问题，如果真的有高并发的时候，就只有一个线程可以修改成功，就会存在大量的失败。</span><br><span class="line"></span><br><span class="line">如果你的应用存在超高并发，这样解决也不好，因为会总让用户感知到失败。</span><br><span class="line"></span><br><span class="line">尝试减小乐观锁力度，最大程度提高吞吐。</span><br><span class="line"></span><br><span class="line">update products set quantity = quantity - <span class="number">1</span> where id = <span class="number">1</span> and quanntity - <span class="number">1</span> &gt; <span class="number">0</span></span><br><span class="line">使用这条 SQL 语句，在执行过程中，会在一次原子操作中查询一遍 quantity 的值，并且减去 <span class="number">1</span>。</span><br><span class="line">laravel 悲观锁对应 lockForUpdate，乐观锁对应 sharedLock https:<span class="comment">//learnku.com/docs/laravel/5.8/queries/3926</span></span><br></pre></td></tr></table></figure>
<p><img src="https://iocaffcdn.phphub.org/uploads/images/201904/24/27516/LoRNLmbvjW.png!large" alt=""><br><img src="https://iocaffcdn.phphub.org/uploads/images/201904/24/27516/DnQMqeCmUn.png!large" alt=""></p>
<h3 id="mysql-8-0-使用简单密码"><a href="#mysql-8-0-使用简单密码" class="headerlink" title="mysql 8.0 使用简单密码"></a>mysql 8.0 使用简单密码</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">直接在 my.cnf 配置文件中 [mysqld] 部分加入下面参数，然后重启 mysqld 即可。</span><br><span class="line"></span><br><span class="line">validate_password.policy = <span class="number">0</span></span><br><span class="line">validate_password.mixed_case_count = <span class="number">0</span></span><br><span class="line">validate_password.number_count = <span class="number">0</span></span><br><span class="line">validate_password.special_char_count = <span class="number">0</span></span><br><span class="line">validate_password.length = <span class="number">0</span></span><br><span class="line">validate_password.policy</span><br><span class="line"></span><br><span class="line">可以配置密码的复杂度，可以配置的级别：</span><br><span class="line"></span><br><span class="line"><span class="number">0</span> or LOW</span><br><span class="line"><span class="number">1</span> or MEDIUM</span><br><span class="line"><span class="number">2</span> or STRONG</span><br><span class="line">validate_password.length</span><br><span class="line"></span><br><span class="line">最终密码的长度，允许为 <span class="number">0</span> ，但是要注意这里有个坑，validate_password.length 的长度要大于 validate_password.mixed_case_count + validate_password.number_count + validate_password.special_char_count 的和。 例如默认这 <span class="number">3</span> 个 参数的长度都是 <span class="number">1</span>， 所以密码长度最小也只能是 <span class="number">4</span>， 即使配置成了 <span class="number">1</span> 或者 <span class="number">0</span> ，最终它也会自动变成 <span class="number">4</span> 。 要是想使用 <span class="number">0</span> 的长度，需要将另外三个参数也配置成 <span class="number">0</span> 。</span><br><span class="line">https:<span class="comment">//broqiang.com/posts/mysql-8-0-uses-a-simple-password</span></span><br></pre></td></tr></table></figure>
<h3 id="Mysql-批量更新多行"><a href="#Mysql-批量更新多行" class="headerlink" title="Mysql 批量更新多行"></a>Mysql 批量更新多行</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">update test set test.sex = <span class="keyword">case</span> name</span><br><span class="line">	when <span class="string">'小白'</span> then <span class="number">2</span></span><br><span class="line">	when <span class="string">'小红'</span> then <span class="number">2</span></span><br><span class="line">	<span class="keyword">else</span> <span class="number">11</span></span><br><span class="line">	end</span><br><span class="line">where name <span class="keyword">in</span> (<span class="string">'小白'</span>,<span class="string">'小红'</span>) and test.group = <span class="number">1</span></span><br><span class="line">https:<span class="comment">//www.h57.pw/2016/09/11/mysql-batch-update-multiline-notes/</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL中的注释符"><a href="#MySQL中的注释符" class="headerlink" title="MySQL中的注释符"></a>MySQL中的注释符</h3><pre><code># 注释从#字符到行尾
-- 注释从–序列到行尾，后面需要跟上一个或多个空格，tab也可以
/* */ 注释中间的字符
</code></pre><h3 id="获取元数据"><a href="#获取元数据" class="headerlink" title="获取元数据"></a>获取元数据</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"> 获取当前的数据库用户，数据库名称，数据库的版本信息</span><br><span class="line">select user(),database(),version() <span class="keyword">from</span> dual;</span><br><span class="line"># 查询数据库，有时需要限制返回的数量，或者偏移，例如页面只显示一条数据的情况 limit 0,1 limit 1,2</span><br><span class="line"># 需要通过偏移来返回所有的数据库</span><br><span class="line">select schema_name <span class="keyword">from</span> information_schema.schemata;</span><br><span class="line"># group_concat 函数是将多行数据连接成一行</span><br><span class="line">select group_concat(schema_name) <span class="keyword">from</span> information_schema.schemata;</span><br><span class="line"># 查询表</span><br><span class="line"># 方法1</span><br><span class="line">select group_concat(table_name) <span class="keyword">from</span> information_schema.tables where table_schema=database();  </span><br><span class="line"># 方法2</span><br><span class="line">select table_name <span class="keyword">from</span> information_schema.tables where table_schema=<span class="string">'database_name'</span>;</span><br><span class="line"># 方法3</span><br><span class="line">select table_name <span class="keyword">from</span> information_schema.tables where table_schema=(select database());</span><br><span class="line"></span><br><span class="line"># 查询列</span><br><span class="line">select column_name <span class="keyword">from</span> information_schema.columns where table_schema=<span class="string">'database_name'</span> and table_name=<span class="string">'users'</span>;</span><br><span class="line">select group_concat(column_name) <span class="keyword">from</span> information_schema.columns where table_schema=database() and table_name=<span class="string">'flag'</span>;</span><br><span class="line"></span><br><span class="line"># 上面可能会被waf识别，也可以这样</span><br><span class="line">select group_concat(column_name) <span class="keyword">from</span> information_schema.columns where table_name=<span class="string">'users'</span>;</span><br><span class="line"></span><br><span class="line"># 字符串可以转换成16进制</span><br><span class="line">select concat(group_concat(distinct+column_name)) <span class="keyword">from</span> information_schema.columns where table_name=<span class="number">0x696e666f</span>;</span><br><span class="line"><span class="string">``</span><span class="string">`   </span></span><br><span class="line"><span class="string">### max key length is 767</span></span><br><span class="line"><span class="string">`</span><span class="string">``</span>javascript</span><br><span class="line">使用 mysql5<span class="number">.7</span> 没有问题，可以正常 migrate,</span><br><span class="line">使用 mysql5<span class="number">.6</span> 时，就出现这个问题，把字段长度缩小可以解决</span><br><span class="line">由于 MySQL Innodb 引擎表索引字段长度的限制为 <span class="number">767</span> 字节，因此对于多字节字符集的大字段（或者多字段组合索引），创建索引会出现上面的错误。</span><br><span class="line">以 utf8mb4 字符集 字符串类型字段为例：utf8mb4 是 <span class="number">4</span> 字节字符集，则默认支持的索引字段最大长度是： <span class="number">767</span> 字节 / <span class="number">4</span> 字节每字符 = <span class="number">191</span> 字符，因此在 varchar (<span class="number">255</span>) 或 char (<span class="number">255</span>) 类型字段上创建索引会失败。https:<span class="comment">//learnku.com/laravel/t/28819</span></span><br><span class="line">处理方案：在 App\Providers\AppServiceProvider 的 boot () 方法中添加 \Illuminate\Support\Facades\Schema::defaultStringLength(<span class="number">191</span>); 即可</span><br></pre></td></tr></table></figure>
<h3 id="SQL-注入"><a href="#SQL-注入" class="headerlink" title="SQL 注入"></a>SQL 注入</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line">select * <span class="keyword">from</span> user where username=<span class="string">''</span> and pass=<span class="string">''</span></span><br><span class="line"># 构造 username=devnull' or '1后，sql 语句变成</span><br><span class="line">select * <span class="keyword">from</span> user where username=<span class="string">'devnull'</span> or <span class="string">'1'</span> and pass=<span class="string">''</span></span><br><span class="line">SELECT * <span class="keyword">from</span> users t where t.username=a()</span><br><span class="line"><span class="comment">// 报错信息，数据库名是 test_db</span></span><br><span class="line">[Err] <span class="number">1305</span> - FUNCTION test_db.a does not exist</span><br><span class="line"># 原始的</span><br><span class="line">http:<span class="comment">//192.168.137.140/cms/show.php?id=35</span></span><br><span class="line"># 后面加上 order by 数字，就会按照第几个字段进行排序，如果没有会报错</span><br><span class="line">http:<span class="comment">//192.168.137.140/cms/show.php?id=35 order by 16</span></span><br><span class="line">mysql执行：语句正常；</span><br><span class="line"># mssql执行：语句错误，数据类型不匹配，无法正常执行</span><br><span class="line">select id,username <span class="keyword">from</span> users union select <span class="number">1</span>,<span class="number">2</span>;     </span><br><span class="line"></span><br><span class="line"># oracle执行：语句错误，数据类型不匹配</span><br><span class="line">select id,username <span class="keyword">from</span> users union select <span class="number">1</span>,<span class="number">2</span> <span class="keyword">from</span> dual;</span><br><span class="line"><span class="comment">// 使用括号，select, from , where 这些关键字不能用括号</span></span><br><span class="line">select(table_name)<span class="keyword">from</span>(information_schema.tables)where(table_schema)=database()</span><br><span class="line"><span class="comment">// 使用内联注释</span></span><br><span class="line">select<span class="comment">/*1*/</span>username<span class="comment">/*1*/</span><span class="keyword">from</span><span class="comment">/*1*/</span>users</span><br><span class="line"><span class="comment">// 使用%0a 绕过</span></span><br><span class="line"><span class="number">1</span> or <span class="number">1</span> == <span class="number">0x31206f722031</span></span><br><span class="line">不区分大小写</span><br><span class="line">select * <span class="keyword">from</span> table_name where a like <span class="string">'a%'</span></span><br><span class="line">select * <span class="keyword">from</span> table_name where a regexp <span class="string">'^a'</span></span><br><span class="line"></span><br><span class="line"># 区分大小写</span><br><span class="line">select * <span class="keyword">from</span> table_name where binary a like <span class="string">'a%'</span></span><br><span class="line">select * <span class="keyword">from</span> table_name where binary a regexp <span class="string">'^a'</span></span><br><span class="line">如果是数字开头的，则会变成前面的字符串 </span><br><span class="line"><span class="string">'123abc'</span> == <span class="number">123</span></span><br><span class="line"><span class="string">'abc'</span> == <span class="number">0</span></span><br><span class="line"># 可以把username不以数字开头的数据取出来</span><br><span class="line">select * <span class="keyword">from</span> users WHERE username=<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">#  'abc' + 0 为 0</span><br><span class="line">select <span class="string">'abc'</span> + <span class="number">0</span>;</span><br><span class="line">#  'abc' + 123 为 123</span><br><span class="line">select <span class="string">'abc'</span> + <span class="number">123</span>;</span><br><span class="line"># 'abc' + '0' 为 0，做加法运算的时候，两边都变成数字 </span><br><span class="line">select <span class="string">'abc'</span> + <span class="string">'0'</span>;</span><br><span class="line">获取所有用户名和密码不为<span class="number">0</span>的数据，利用这种方式可以构造万能密码</span><br><span class="line"></span><br><span class="line"> et/<span class="number">2018</span>/<span class="number">10</span>/<span class="number">29</span>/ctf-sqli-notes/</span><br><span class="line">select * <span class="keyword">from</span> users where username=<span class="number">0</span> and password=<span class="number">0</span></span><br><span class="line">select * <span class="keyword">from</span> users where username=<span class="string">'abcd'</span> + <span class="string">'0'</span> and password=<span class="string">'abc'</span> + <span class="string">'0'</span></span><br><span class="line"><span class="string">``</span><span class="string">` </span></span><br><span class="line"><span class="string">### limit 优化</span></span><br><span class="line"><span class="string">`</span><span class="string">``</span>javascript</span><br><span class="line">在偏移量非常大的时候，例如可能是LIMIT <span class="number">1000</span>,<span class="number">20</span>这样的查询，这时MySQL需要查询<span class="number">10020</span>条记录然后只返回最后<span class="number">20</span>条，前面<span class="number">1000</span>条记录都被抛弃，这样的代价非常高。如果所有的页面被访问的频率相同，那么这样的查询平均需要访问半个表的数据。要优化这种查询，要么是在页面中限制分页的数量，要么是优化大偏移量的性能。</span><br><span class="line"></span><br><span class="line">优化此类分页查询的一个最简单的办法就是尽可能地使用索引覆盖扫描，而不是查询所有的列。考虑下面的查询：</span><br><span class="line"></span><br><span class="line">select id,desc <span class="keyword">from</span> film order by title limit <span class="number">50000</span>,<span class="number">10</span>;</span><br><span class="line"></span><br><span class="line">select id,desc <span class="keyword">from</span> file inner join (select id <span class="keyword">from</span> file order by title limit <span class="number">50000</span>,<span class="number">10</span>) b on film.id=b.id;</span><br><span class="line">”延迟关联“将大大提升查询效率，它让MySQL扫描尽可能少的页面，获取需要访问的记录后再根据关联列回元表查询需要的所有列。这个技术也可以用于优化关联查询中的LIMIT子句。</span><br><span class="line"></span><br><span class="line">LIMIT和OFFSET的问题，其实是OFFSET的问题，它会导致MySQL扫描达赖给你不需要的行然后再抛弃掉。如果可以使用书签记录上次取数据的位置，那么下次就可以直接从该书签记录得位置开始扫描，这样就可以避免使用OFFSET。</span><br><span class="line"></span><br><span class="line">select id,desc <span class="keyword">from</span> film where id&gt;<span class="number">5000</span> limit <span class="number">10</span>;</span><br><span class="line">https:<span class="comment">//shuwoom.com/?p=2659</span></span><br></pre></td></tr></table></figure>
<h3 id="取出一组热门作者及他们最近发表的-3-篇文章"><a href="#取出一组热门作者及他们最近发表的-3-篇文章" class="headerlink" title="取出一组热门作者及他们最近发表的 3 篇文章"></a>取出一组热门作者及他们最近发表的 3 篇文章</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">$users = \App\Models\User::limit(<span class="number">10</span>)-&gt;get();</span><br><span class="line"></span><br><span class="line">$users = $users-&gt;map(<span class="function"><span class="keyword">function</span> (<span class="params">$user</span>) </span>&#123;</span><br><span class="line">    <span class="comment">//可以考虑$user-&gt;id缓存,在保证了速度的同时避免大面积的缓存重建</span></span><br><span class="line">    $user-&gt;posts = $user-&gt;posts()-&gt;limit(<span class="number">3</span>)-&gt;get();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> $user;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> $users;</span><br><span class="line">SELECT</span><br><span class="line">    posts.*,</span><br><span class="line">    @number := IF (@current_user_id = <span class="string">`user_id`</span>, @number + <span class="number">1</span>, <span class="number">1</span>) AS number,</span><br><span class="line">    @current_user_id := <span class="string">`user_id`</span></span><br><span class="line">FROM</span><br><span class="line">    (select * <span class="keyword">from</span> <span class="string">`posts`</span> where <span class="string">`posts`</span>.<span class="string">`user_id`</span> IN (<span class="number">572</span>, <span class="number">822</span>, <span class="number">911</span>, <span class="number">103</span>, <span class="number">234</span>, <span class="number">11</span>, <span class="number">999</span>, <span class="number">333</span>, <span class="number">121</span>, <span class="number">122</span>) order by <span class="string">`posts`</span>.<span class="string">`user_id`</span> ASC) AS posts</span><br><span class="line">HAVING</span><br><span class="line">    number &lt;= <span class="number">3</span></span><br><span class="line">简单解析一下这个 sql 语句.</span><br><span class="line">https:<span class="comment">//learnku.com/articles/24787#replies</span></span><br><span class="line">FORM 为一个子查询，初步筛选出我们需要的作者的所有文章，且正序排列后生成一个临时表.</span><br><span class="line"></span><br><span class="line">SELECT 为上面临时表添加标号，添加的方式如下. (你需要从上往下一行行一行的观察，与 select 的执行方式一致即可)</span><br><span class="line"></span><br><span class="line">MySQL 中调用未定义的变量，其值默认为 <span class="literal">null</span>.</span><br><span class="line">id	user_id	@current_user_id	<span class="keyword">if</span> 判断	@number</span><br><span class="line"><span class="number">1</span>	<span class="number">1</span>	<span class="literal">null</span>	<span class="literal">false</span>, number 被赋值为 <span class="number">1</span>	<span class="number">1</span></span><br><span class="line"><span class="number">2</span>	<span class="number">1</span>	<span class="number">1</span>	<span class="literal">true</span>, @number = @number + <span class="number">1</span>	<span class="number">2</span></span><br><span class="line"><span class="number">3</span>	<span class="number">1</span>	<span class="number">1</span>	<span class="literal">true</span>, @number = @number + <span class="number">1</span>	<span class="number">3</span></span><br><span class="line"><span class="number">4</span>	<span class="number">1</span>	<span class="number">1</span>	<span class="literal">true</span>, @number = @number + <span class="number">1</span>	<span class="number">4</span></span><br><span class="line"><span class="number">5</span>	<span class="number">2</span>	<span class="number">1</span>	<span class="literal">false</span>, number 被赋值为 <span class="number">1</span>	<span class="number">1</span></span><br><span class="line"><span class="number">6</span>	<span class="number">2</span>	<span class="number">2</span>	<span class="literal">true</span>, @number = @number + <span class="number">1</span>	<span class="number">2</span></span><br><span class="line">..	..	..	..	..</span><br><span class="line">HAVING 执行于 SELECT 之后，其再次筛选上面的临时表，只取 number &lt;= <span class="number">3</span> 的 行.</span><br><span class="line"></span><br><span class="line">select *, substring_index(group_concat(id order by id desc), <span class="string">','</span>, <span class="number">10</span>) <span class="keyword">from</span> orders</span><br><span class="line">group by sid;</span><br><span class="line"></span><br><span class="line">User::<span class="keyword">with</span>([<span class="string">'posts'</span>=&gt;<span class="function"><span class="keyword">function</span>(<span class="params">$query</span>)</span>&#123;</span><br><span class="line">            $query-&gt;whereRaw(<span class="string">'3 &gt; (select count(*) from posts as sub where sub.user_id = posts.user_id and sub.id &gt; posts.id ) '</span>)</span><br><span class="line">            -&gt;orderByDesc(<span class="string">'id'</span>);</span><br><span class="line">        &#125;])-&gt;get();</span><br></pre></td></tr></table></figure>
<h3 id="多更新"><a href="#多更新" class="headerlink" title="多更新"></a>多更新</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">update your_table set is_default = (<span class="keyword">case</span> when id = <span class="number">3</span> then <span class="number">1</span> <span class="keyword">else</span> <span class="number">0</span> end)</span><br></pre></td></tr></table></figure>
<h3 id="MySQL-调优经历"><a href="#MySQL-调优经历" class="headerlink" title="MySQL 调优经历"></a>MySQL 调优经历</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line">create table <span class="string">`users`</span> (</span><br><span class="line">  <span class="string">`id`</span> int(<span class="number">10</span>) unsigned not <span class="literal">null</span> auto_increment,</span><br><span class="line">  <span class="string">`name`</span> varchar(<span class="number">255</span>) <span class="keyword">default</span> <span class="string">'name'</span>,</span><br><span class="line">  <span class="string">`a`</span> varchar(<span class="number">255</span>) <span class="keyword">default</span> <span class="string">'aaaaaaaaaaaaaaaa'</span>,</span><br><span class="line">  <span class="string">`b`</span> varchar(<span class="number">255</span>) <span class="keyword">default</span> <span class="string">'bbbbbbbbbbbbbbbb'</span>,</span><br><span class="line">  <span class="string">`c`</span> varchar(<span class="number">255</span>) <span class="keyword">default</span> <span class="string">'cccccccccccccccc'</span>,</span><br><span class="line">  primary key (<span class="string">`id`</span>)</span><br><span class="line">) engine=innodb;</span><br><span class="line">delimiter ;;</span><br><span class="line">  create procedure usersdata()</span><br><span class="line">  begin</span><br><span class="line">    declare i int;</span><br><span class="line">    set i=<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span>(i&lt;=<span class="number">4000</span>)<span class="keyword">do</span></span><br><span class="line">      insert into users(<span class="string">`name`</span>) values(<span class="string">'name'</span>);</span><br><span class="line">      set i=i+<span class="number">1</span>;</span><br><span class="line">    end <span class="keyword">while</span>;</span><br><span class="line">  end;;</span><br><span class="line">delimiter ;</span><br><span class="line">call usersdata();</span><br><span class="line">create table <span class="string">`user_enterprises`</span> (</span><br><span class="line">  <span class="string">`id`</span> int(<span class="number">11</span>) unsigned not <span class="literal">null</span> auto_increment,</span><br><span class="line">  <span class="string">`user_id`</span> int(<span class="number">11</span>) <span class="keyword">default</span> <span class="literal">null</span>,</span><br><span class="line">  primary key (<span class="string">`id`</span>)</span><br><span class="line">) engine=innodb;</span><br><span class="line">delimiter ;;</span><br><span class="line">  create procedure enterprisesdata()</span><br><span class="line">  begin</span><br><span class="line">    declare i int;</span><br><span class="line">    set i=<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span>(i&lt;=<span class="number">4000</span>)<span class="keyword">do</span></span><br><span class="line">      insert into user_enterprises(<span class="string">`user_id`</span>) values(i);</span><br><span class="line">      set i=i+<span class="number">1</span>;</span><br><span class="line">    end <span class="keyword">while</span>;</span><br><span class="line">  end;;</span><br><span class="line">delimiter ;</span><br><span class="line">call enterprisesdata();</span><br><span class="line">select * <span class="keyword">from</span> <span class="string">`users`</span> left join <span class="string">`user_enterprises`</span> on <span class="string">`users`</span>.<span class="string">`id`</span> = <span class="string">`user_enterprises`</span>.<span class="string">`user_id`</span> order by <span class="string">`users`</span>.<span class="string">`id`</span> desc;</span><br><span class="line">首先把 users 表的所有数据加入到 join buffer 中。</span><br><span class="line">扫描整个 user_enterprises 表的每一行数据，与 join buffer 中的 users 数据作对比，将满足条件的加入结果集。</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 打开 optimizer_trace，只对本线程有效 */</span></span><br><span class="line">SET optimizer_trace=<span class="string">'enabled=on'</span>; </span><br><span class="line"></span><br><span class="line"><span class="comment">/* @a 保存 Innodb_rows_read 的初始值 */</span></span><br><span class="line">select VARIABLE_VALUE into @a <span class="keyword">from</span>  performance_schema.session_status where variable_name = <span class="string">'Innodb_rows_read'</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 执行语句 */</span></span><br><span class="line">select * <span class="keyword">from</span> <span class="string">`users`</span> left join <span class="string">`user_enterprises`</span> on <span class="string">`users`</span>.<span class="string">`id`</span> = <span class="string">`user_enterprises`</span>.<span class="string">`user_id`</span> order by <span class="string">`users`</span>.<span class="string">`id`</span> desc;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* @b 保存 Innodb_rows_read 的当前值 */</span></span><br><span class="line">select VARIABLE_VALUE into @b <span class="keyword">from</span> performance_schema.session_status where variable_name = <span class="string">'Innodb_rows_read'</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 计算 Innodb_rows_read 差值 */</span></span><br><span class="line">select @b-@a;</span><br><span class="line">我们得到的扫描行数是 <span class="number">12000</span>。在执行 join 的时候，扫描行数应该是 <span class="number">4000</span> + <span class="number">4000</span>，还有 <span class="number">4000</span> 的扫描行数我推测应该是回表取了数据。</span><br><span class="line"></span><br><span class="line">启用 optimizer_trace 调试：</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 打开 optimizer_trace，只对本线程有效 */</span></span><br><span class="line">set optimizer_trace=<span class="string">'enabled=on'</span>; </span><br><span class="line"></span><br><span class="line"><span class="comment">/* 执行语句 */</span></span><br><span class="line">select * <span class="keyword">from</span> <span class="string">`users`</span> left join <span class="string">`user_enterprises`</span> on <span class="string">`users`</span>.<span class="string">`id`</span> = <span class="string">`user_enterprises`</span>.<span class="string">`user_id`</span> order by <span class="string">`users`</span>.<span class="string">`id`</span> desc;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 查看 OPTIMIZER_TRACE 输出 */</span></span><br><span class="line">select * <span class="keyword">from</span> <span class="string">`information_schema`</span>.<span class="string">`optimizer_trace`</span>;</span><br><span class="line">我们看到使用的排序方法是 rowid 排序，select @@max_length_for_sort_data 的结果为 <span class="number">1024</span>，即参与排序的字段大于了这个值，mysql 会把排序字段和主键取出来放入 sort buffer，完成排序后回表取数据。在这儿还用到了临时表。所以大致执行过程应该是 join 之后把数据存在了临时表，然后使用 rowid 排序。</span><br><span class="line"></span><br><span class="line">从上面我们发现这个过程是复杂的，如果在 user_enterprises 表上给 user_id 加上索引。</span><br><span class="line"></span><br><span class="line">alter table <span class="string">`user_enterprises`</span> add key <span class="string">`user_id_index`</span> (<span class="string">`user_id`</span>);</span><br><span class="line"></span><br><span class="line">首先 join 的执行流程发生了变化，大体流程是：</span><br><span class="line"></span><br><span class="line">在 users 表里取出一行数据</span><br><span class="line">根据索引在 user_enterprises 表里获取结果，组成结果集</span><br><span class="line">我们发现使用到了索引后，就没有在 join buffer 里那些复杂操作了。因为索引的有序性，排序也免了，整个查询过程所需要的时间也大大减少。https:<span class="comment">//learnku.com/articles/28964</span></span><br></pre></td></tr></table></figure>
<h3 id="exists"><a href="#exists" class="headerlink" title="exists"></a>exists</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">https:<span class="comment">//learnku.com/articles/29168</span></span><br><span class="line">SELECT </span><br><span class="line">sql_no_cache <span class="string">`product_id`</span></span><br><span class="line">FROM</span><br><span class="line"><span class="string">`zx_tests`</span> AS a</span><br><span class="line">WHERE</span><br><span class="line"><span class="string">`pn_id`</span> = <span class="number">101</span> AND <span class="string">`pv_id`</span> = <span class="number">59</span></span><br><span class="line">    AND EXISTS( SELECT </span><br><span class="line">       sql_no_cache  *</span><br><span class="line">    FROM</span><br><span class="line">        <span class="string">`zx_tests`</span></span><br><span class="line">    WHERE</span><br><span class="line">    a.product_id = product_id and</span><br><span class="line">        <span class="string">`pn_id`</span> = <span class="number">101</span> AND <span class="string">`pv_id`</span> = <span class="number">171</span>);</span><br><span class="line"></span><br><span class="line"><span class="number">2</span> 组条件下 <span class="number">0.657</span>，<span class="number">3</span> 组 <span class="number">0.695</span>，<span class="number">4</span> 组 <span class="number">0.759</span>，<span class="number">5</span> 组 <span class="number">0.743</span></span><br><span class="line">SELECT <span class="string">`product_id`</span> FROM <span class="string">`product`</span> WHERE <span class="string">`pn_id`</span> = <span class="number">5</span> AND <span class="string">`pv_id`</span> = <span class="number">135</span> AND <span class="string">`product_id`</span> IN (SELECT <span class="string">`product_id`</span> FROM <span class="string">`product`</span> WHERE <span class="string">`pn_id`</span> = <span class="number">11</span> AND <span class="string">`pv_id`</span> = <span class="number">23</span>);</span><br><span class="line"></span><br><span class="line">    <span class="number">2</span> 组条件下 <span class="number">0.729</span>，<span class="number">3</span> 组 <span class="number">0.75</span>，<span class="number">4</span> 组 <span class="number">0.730</span>，<span class="number">5</span> 组 <span class="number">0.757</span></span><br></pre></td></tr></table></figure>
<h3 id="批量更新所有字段字符集"><a href="#批量更新所有字段字符集" class="headerlink" title="批量更新所有字段字符集"></a>批量更新所有字段字符集</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">begin</span><br><span class="line">    declare f_name varchar(<span class="number">100</span>); </span><br><span class="line">    declare b int <span class="keyword">default</span> <span class="number">0</span>;    <span class="comment">/*是否达到记录的末尾控制变量*/</span></span><br><span class="line">		-- 注意修改下面的数据库名称 wsm_aliyun</span><br><span class="line">    declare table_name cursor <span class="keyword">for</span> SELECT TABLE_NAME FROM information_schema.TABLES where TABLE_SCHEMA = <span class="string">'construction_online'</span>;</span><br><span class="line">    DECLARE CONTINUE HANDLER FOR NOT FOUND SET b = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">    OPEN table_name;</span><br><span class="line">    REPEAT</span><br><span class="line">    FETCH table_name INTO f_name; <span class="comment">/*获取第一条记录*/</span></span><br><span class="line">				SET @STMT :=CONCAT(<span class="string">"ALTER TABLE "</span>,f_name,<span class="string">" CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"</span>);   </span><br><span class="line">			PREPARE STMT FROM @STMT;   </span><br><span class="line">    EXECUTE STMT;  </span><br><span class="line">-- INSERT into TestTable(name) VALUES (f_name);</span><br><span class="line">       -- ALTER TABLE f_name CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; </span><br><span class="line">    UNTIL b = <span class="number">1</span></span><br><span class="line">		END REPEAT;</span><br><span class="line">    close table_name;</span><br><span class="line">end</span><br><span class="line">https:<span class="comment">//wi1dcard.cn/posts/mysql-update-all-collations/</span></span><br></pre></td></tr></table></figure>
<h3 id="每门科目成绩前三的数据"><a href="#每门科目成绩前三的数据" class="headerlink" title="每门科目成绩前三的数据"></a>每门科目成绩前三的数据</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">表：student_score，姓名：name，科目：subject，分数 score</span><br><span class="line">SELECT</span><br><span class="line">    a.*</span><br><span class="line">FROM</span><br><span class="line">    student AS a</span><br><span class="line">LEFT JOIN student AS b ON a.<span class="string">`subject`</span> = b.<span class="string">`subject`</span></span><br><span class="line">AND a.score &lt; b.score</span><br><span class="line">GROUP BY</span><br><span class="line">    a.id,</span><br><span class="line">    a. SUBJECT,</span><br><span class="line">    a.score</span><br><span class="line">HAVING</span><br><span class="line">    COUNT(b.id) &lt; <span class="number">3</span></span><br><span class="line">ORDER BY</span><br><span class="line">    a.<span class="string">`subject`</span>,</span><br><span class="line">    a.score DESC</span><br></pre></td></tr></table></figure>
<h3 id="删除表中重复数据，并保留一条"><a href="#删除表中重复数据，并保留一条" class="headerlink" title="删除表中重复数据，并保留一条"></a>删除表中重复数据，并保留一条</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">DELETE FROM student WHERE</span><br><span class="line">(<span class="string">`name`</span>,<span class="string">`subject`</span>,score) IN (</span><br><span class="line">    SELECT t.name,t.subject,t.score FROM (</span><br><span class="line">        SELECT <span class="string">`name`</span>,<span class="string">`subject`</span>,score FROM student </span><br><span class="line">        GROUP BY <span class="string">`name`</span>,<span class="string">`subject`</span>,score </span><br><span class="line">        HAVING COUNT(<span class="number">1</span>)&gt;<span class="number">1</span></span><br><span class="line">    )t</span><br><span class="line">)</span><br><span class="line">AND id not <span class="keyword">in</span>(</span><br><span class="line">  SELECT a.minId FROM (</span><br><span class="line">        SELECT id <span class="keyword">as</span> minId FROM student </span><br><span class="line">        GROUP BY <span class="string">`name`</span>,<span class="string">`subject`</span>,score </span><br><span class="line">        HAVING COUNT(<span class="number">1</span>)&gt;<span class="number">1</span></span><br><span class="line">    )a</span><br><span class="line">)</span><br><span class="line">所有科目成绩都大于 <span class="number">80</span> 分的学生数据</span><br><span class="line"></span><br><span class="line">select name <span class="keyword">from</span> student group by name having min(score)&gt;<span class="number">80</span>;</span><br><span class="line">https:<span class="comment">//learnku.com/articles/29467</span></span><br></pre></td></tr></table></figure>
<h3 id="并列排名和顺序排名查询"><a href="#并列排名和顺序排名查询" class="headerlink" title="并列排名和顺序排名查询"></a>并列排名和顺序排名查询</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br></pre></td><td class="code"><pre><span class="line">获取分数排名，要求并列排名。如果两个分数相同，则两个分数排名（rank）相同。名次之间不应该有“间隔”。</span><br><span class="line">id	score</span><br><span class="line"><span class="number">1</span>	<span class="number">99</span></span><br><span class="line"><span class="number">2</span>	<span class="number">80</span></span><br><span class="line"><span class="number">3</span>	<span class="number">87</span></span><br><span class="line"><span class="number">4</span>	<span class="number">60</span></span><br><span class="line"><span class="number">5</span>	<span class="number">80</span></span><br><span class="line"><span class="number">6</span>	<span class="number">99</span></span><br><span class="line">select id, score, (select count(distinct(score)) <span class="keyword">from</span> scores <span class="keyword">as</span> b where b.score &gt; a.score ) + <span class="number">1</span> <span class="keyword">as</span> rank <span class="keyword">from</span> scores <span class="keyword">as</span> a order by rank;</span><br><span class="line"></span><br><span class="line">select id, score, (select count(distinct(score)) <span class="keyword">from</span> scores <span class="keyword">as</span> b where b.score &gt; a.score ) + <span class="number">1</span> <span class="keyword">as</span> rank <span class="keyword">from</span> scores <span class="keyword">as</span> a order by rank;</span><br><span class="line">https:<span class="comment">//learnku.com/articles/27599</span></span><br><span class="line">select t.id, t.score,@rowNum := @rowNum +<span class="number">1</span> <span class="keyword">as</span> rank <span class="keyword">from</span> (select @rowNum :=<span class="number">0</span>) r, scores <span class="keyword">as</span> t order by t.score desc ;</span><br><span class="line"></span><br><span class="line">id	score	rank</span><br><span class="line"><span class="number">1</span>	<span class="number">99</span>	<span class="number">1</span></span><br><span class="line"><span class="number">6</span>	<span class="number">99</span>	<span class="number">1</span></span><br><span class="line"><span class="number">3</span>	<span class="number">87</span>	<span class="number">2</span></span><br><span class="line"><span class="number">2</span>	<span class="number">80</span>	<span class="number">3</span></span><br><span class="line"><span class="number">5</span>	<span class="number">80</span>	<span class="number">3</span></span><br><span class="line"><span class="number">4</span>	<span class="number">60</span>	<span class="number">4</span></span><br><span class="line"></span><br><span class="line"> INNER JOIN...ON...: 返回俩表关联的所有行，不执行上面说的第三部JOIN添加外部行。</span><br><span class="line"> LEFT JOIN...ON... : 返回左表中的所有行，若有些行在右表中没有对应的值，将会使用NULL填充。</span><br><span class="line"> RIGHT JOIN...ON...: 返回右表中的所有行，若有些行在左表中没有对应的值，将会使用NULL填充。</span><br><span class="line"> </span><br><span class="line"> SELECT * FROM user_info <span class="keyword">as</span> i LEFT JOIN user_account <span class="keyword">as</span> a ON i.userid = a.userid and i.userid = <span class="number">1003</span>;</span><br><span class="line"> </span><br><span class="line"> SELECT * FROM user_info <span class="keyword">as</span> i LEFT JOIN user_account <span class="keyword">as</span> a ON i.userid = a.userid where i.userid = <span class="number">1003</span>;</span><br><span class="line"> 第一种情况 LEFT JOIN 在执行完第二步 ON 子句后，筛选出满足 i.userid = a.userid and i.userid = <span class="number">1003</span> 的行，生成表 vt2，然后执行第三步 JOIN 子句，将外部行添加进虚拟表生成 vt3 即最终结果：</span><br><span class="line"> </span><br><span class="line"> vt2:</span><br><span class="line"> | userid | name | userid | money |</span><br><span class="line"> |  --------   |  --------  |   --------   |  --------  |</span><br><span class="line"> |   <span class="number">1003</span> | z    |   <span class="number">1003</span> |     <span class="number">8</span> |</span><br><span class="line"> </span><br><span class="line"> vt3:</span><br><span class="line"> | userid | name | userid | money |</span><br><span class="line"> |  --------   |  --------  |   --------   |  --------  |</span><br><span class="line"> |   <span class="number">1001</span> | x    |   NULL |  NULL |</span><br><span class="line"> |   <span class="number">1002</span> | y    |   NULL |  NULL |</span><br><span class="line"> |   <span class="number">1003</span> | z    |   <span class="number">1003</span> |     <span class="number">8</span> |</span><br><span class="line"> |   <span class="number">1004</span> | a    |   NULL |  NULL |</span><br><span class="line"> |   <span class="number">1005</span> | b    |   NULL |  NULL |</span><br><span class="line"> |   <span class="number">1006</span> | c    |   NULL |  NULL |</span><br><span class="line"> |   <span class="number">1007</span> | d    |   NULL |  NULL |</span><br><span class="line"> |   <span class="number">1008</span> | e    |   NULL |  NULL |</span><br><span class="line"> 而第二种情况 LEFT JOIN 在执行完第二步 ON 子句后，筛选出满足 i.userid = a.userid 的行，生成表 vt2；再执行第三步 JOIN 子句添加外部行生成表 vt3；然后执行第四步 WHERE 子句，再对 vt3 表进行过滤生成 vt4，得的最终结果：</span><br><span class="line"> </span><br><span class="line"> vt2:</span><br><span class="line"> | userid | name | userid | money |</span><br><span class="line"> |  --------   |  --------  |   --------   |  --------  |</span><br><span class="line"> |   <span class="number">1001</span> | x    |   <span class="number">1001</span> |    <span class="number">22</span> |</span><br><span class="line"> |   <span class="number">1002</span> | y    |   <span class="number">1002</span> |    <span class="number">30</span> |</span><br><span class="line"> |   <span class="number">1003</span> | z    |   <span class="number">1003</span> |     <span class="number">8</span> |</span><br><span class="line"> vt3:</span><br><span class="line"> | userid | name | userid | money |</span><br><span class="line"> |  --------   |  --------  |   --------   |  --------  |</span><br><span class="line"> |   <span class="number">1001</span> | x    |   <span class="number">1001</span> |    <span class="number">22</span> |</span><br><span class="line"> |   <span class="number">1002</span> | y    |   <span class="number">1002</span> |    <span class="number">30</span> |</span><br><span class="line"> |   <span class="number">1003</span> | z    |   <span class="number">1003</span> |     <span class="number">8</span> |</span><br><span class="line"> |   <span class="number">1004</span> | a    |   NULL |  NULL |</span><br><span class="line"> |   <span class="number">1005</span> | b    |   NULL |  NULL |</span><br><span class="line"> |   <span class="number">1006</span> | c    |   NULL |  NULL |</span><br><span class="line"> |   <span class="number">1007</span> | d    |   NULL |  NULL |</span><br><span class="line"> |   <span class="number">1008</span> | e    |   NULL |  NULL |</span><br><span class="line"> vt4:</span><br><span class="line"> | userid | name | userid | money |</span><br><span class="line"> |  --------   |  --------  |   --------   |  --------  |</span><br><span class="line"> |   <span class="number">1003</span> | z    |   <span class="number">1003</span> |     <span class="number">8</span> |</span><br><span class="line"> 如果将上例的 LEFT JOIN 替换成 INNER JOIN，不论将条件过滤放到 ON 还是 WHERE 里，结果都是一样的，因为 INNER JOIN 不会执行第三步添加外部行。</span><br><span class="line"> </span><br><span class="line"> SELECT * FROM user_info <span class="keyword">as</span> i INNER JOIN user_account <span class="keyword">as</span> a ON i.userid = a.userid and i.userid = <span class="number">1003</span>;</span><br><span class="line"> SELECT * FROM user_info <span class="keyword">as</span> i INNER JOIN user_account <span class="keyword">as</span> a ON i.userid = a.userid where i.userid = <span class="number">1003</span>;</span><br><span class="line"> 返回结果都是：</span><br><span class="line"> </span><br><span class="line"> | userid | name | userid | money |</span><br><span class="line"> |  --------   |  --------  |   --------   |  --------  |</span><br><span class="line"> |   <span class="number">1003</span> | z    |   <span class="number">1003</span> |     <span class="number">8</span> |</span><br><span class="line"> https:<span class="comment">//learnku.com/articles/27701</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL-分页数据错乱重复"><a href="#MySQL-分页数据错乱重复" class="headerlink" title="MySQL 分页数据错乱重复"></a>MySQL 分页数据错乱重复</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line">select xx <span class="keyword">from</span> table_name wheere xxx order by 字段A limit offset;，</span><br><span class="line">表数据总共 <span class="number">48</span> 条，分页数量正常，但出现了结果混杂的情况，第一页的数据出现在了第二页上；如果 order by 字段B 就不会出现这个现象</span><br><span class="line">mysql <span class="number">5.6</span> </span><br><span class="line">create table glon(  </span><br><span class="line">    -&gt;     id int not <span class="literal">null</span> auto_increment primary key,  </span><br><span class="line">    -&gt;     name varchar(<span class="number">20</span>) not <span class="literal">null</span>,  </span><br><span class="line">    -&gt;     create_time datetime not <span class="literal">null</span>,  </span><br><span class="line">    -&gt;     age tinyint unsigned <span class="keyword">default</span> <span class="number">18</span>  </span><br><span class="line">    -&gt; );</span><br><span class="line">INSERT INTO <span class="string">`glon`</span> VALUES (<span class="number">1</span>, <span class="string">'Eason Chan'</span>, <span class="string">'2017-05-02 08:10:10'</span>, <span class="number">19</span>),(<span class="number">2</span>, <span class="string">'Glon Ho'</span>, <span class="string">'2017-05-03 12:10:10'</span>, <span class="number">18</span>),(<span class="number">3</span>, <span class="string">'赵敏'</span>, <span class="string">'2017-05-03 14:10:10'</span>, <span class="number">17</span>),(<span class="number">4</span>, <span class="string">'Jacky Cheung'</span>, <span class="string">'2017-05-02 14:00:00'</span>, <span class="number">22</span>),(<span class="number">5</span>, <span class="string">'周芷若'</span>, <span class="string">'2017-05-02 14:00:00'</span>, <span class="number">16</span>),(<span class="number">6</span>, <span class="string">'Andy Lau'</span>, <span class="string">'2017-05-02 14:00:00'</span>, <span class="number">50</span>),(<span class="number">7</span>, <span class="string">'至尊宝'</span>, <span class="string">'2017-05-02 14:00:00'</span>, <span class="number">20</span>),(<span class="number">8</span>, <span class="string">'刘三姐'</span>, <span class="string">'2017-05-02 14:00:00'</span>, <span class="number">19</span>);</span><br><span class="line"></span><br><span class="line">root@localhost [glon_ho]&gt;select * <span class="keyword">from</span> glon;</span><br><span class="line">+----+--------------+---------------------+------+</span><br><span class="line">| id | name         | create_time         | age  |</span><br><span class="line">+----+--------------+---------------------+------+</span><br><span class="line">|  <span class="number">1</span> | Eason Chan   | <span class="number">2017</span><span class="number">-05</span><span class="number">-02</span> <span class="number">08</span>:<span class="number">10</span>:<span class="number">10</span> |   <span class="number">19</span> |</span><br><span class="line">|  <span class="number">2</span> | Glon Ho      | <span class="number">2017</span><span class="number">-05</span><span class="number">-03</span> <span class="number">12</span>:<span class="number">10</span>:<span class="number">10</span> |   <span class="number">18</span> |</span><br><span class="line">|  <span class="number">3</span> | 赵敏         | <span class="number">2017</span><span class="number">-05</span><span class="number">-03</span> <span class="number">14</span>:<span class="number">10</span>:<span class="number">10</span> |   <span class="number">17</span> |</span><br><span class="line">|  <span class="number">4</span> | Jacky Cheung | <span class="number">2017</span><span class="number">-05</span><span class="number">-02</span> <span class="number">14</span>:<span class="number">00</span>:<span class="number">00</span> |   <span class="number">22</span> |</span><br><span class="line">|  <span class="number">5</span> | 周芷若       | <span class="number">2017</span><span class="number">-05</span><span class="number">-02</span> <span class="number">14</span>:<span class="number">00</span>:<span class="number">00</span> |   <span class="number">16</span> |</span><br><span class="line">|  <span class="number">6</span> | Andy Lau     | <span class="number">2017</span><span class="number">-05</span><span class="number">-02</span> <span class="number">14</span>:<span class="number">00</span>:<span class="number">00</span> |   <span class="number">50</span> |</span><br><span class="line">|  <span class="number">7</span> | 至尊宝       | <span class="number">2017</span><span class="number">-05</span><span class="number">-02</span> <span class="number">14</span>:<span class="number">00</span>:<span class="number">00</span> |   <span class="number">20</span> |</span><br><span class="line">|  <span class="number">8</span> | 刘三姐       | <span class="number">2017</span><span class="number">-05</span><span class="number">-02</span> <span class="number">14</span>:<span class="number">00</span>:<span class="number">00</span> |   <span class="number">19</span> |</span><br><span class="line">+----+--------------+---------------------+------+</span><br><span class="line"></span><br><span class="line">root@localhost [glon_ho]&gt;select * <span class="keyword">from</span> glon ORDER BY create_time limit <span class="number">0</span>, <span class="number">4</span>;</span><br><span class="line">+----+--------------+---------------------+------+</span><br><span class="line">| id | name         | create_time         | age  |</span><br><span class="line">+----+--------------+---------------------+------+</span><br><span class="line">|  <span class="number">1</span> | Eason Chan   | <span class="number">2017</span><span class="number">-05</span><span class="number">-02</span> <span class="number">08</span>:<span class="number">10</span>:<span class="number">10</span> |   <span class="number">19</span> |</span><br><span class="line">|  <span class="number">8</span> | 刘三姐       | <span class="number">2017</span><span class="number">-05</span><span class="number">-02</span> <span class="number">14</span>:<span class="number">00</span>:<span class="number">00</span> |   <span class="number">19</span> |</span><br><span class="line">|  <span class="number">6</span> | Andy Lau     | <span class="number">2017</span><span class="number">-05</span><span class="number">-02</span> <span class="number">14</span>:<span class="number">00</span>:<span class="number">00</span> |   <span class="number">50</span> |</span><br><span class="line">|  <span class="number">4</span> | Jacky Cheung | <span class="number">2017</span><span class="number">-05</span><span class="number">-02</span> <span class="number">14</span>:<span class="number">00</span>:<span class="number">00</span> |   <span class="number">22</span> |</span><br><span class="line">+----+--------------+---------------------+------+</span><br><span class="line"><span class="number">4</span> rows <span class="keyword">in</span> set (<span class="number">0.00</span> sec)</span><br><span class="line"></span><br><span class="line">root@localhost [glon_ho]&gt;select * <span class="keyword">from</span> glon ORDER BY create_time limit <span class="number">4</span>, <span class="number">4</span>;</span><br><span class="line">+----+-----------+---------------------+------+</span><br><span class="line">| id | name      | create_time         | age  |</span><br><span class="line">+----+-----------+---------------------+------+</span><br><span class="line">|  <span class="number">7</span> | 至尊宝    | <span class="number">2017</span><span class="number">-05</span><span class="number">-02</span> <span class="number">14</span>:<span class="number">00</span>:<span class="number">00</span> |   <span class="number">20</span> |</span><br><span class="line">|  <span class="number">8</span> | 刘三姐    | <span class="number">2017</span><span class="number">-05</span><span class="number">-02</span> <span class="number">14</span>:<span class="number">00</span>:<span class="number">00</span> |   <span class="number">19</span> |</span><br><span class="line">|  <span class="number">2</span> | Glon Ho   | <span class="number">2017</span><span class="number">-05</span><span class="number">-03</span> <span class="number">12</span>:<span class="number">10</span>:<span class="number">10</span> |   <span class="number">18</span> |</span><br><span class="line">|  <span class="number">3</span> | 赵敏      | <span class="number">2017</span><span class="number">-05</span><span class="number">-03</span> <span class="number">14</span>:<span class="number">10</span>:<span class="number">10</span> |   <span class="number">17</span> |</span><br><span class="line">+----+-----------+---------------------+------+</span><br><span class="line"><span class="number">4</span> rows <span class="keyword">in</span> set (<span class="number">0.00</span> sec)</span><br><span class="line"></span><br><span class="line">两次查询结果中都出现了 id 为 <span class="number">8</span> 的刘三姐，从上面初始化数据来看，总共有 <span class="number">8</span> 条数据，现在不但分页出现重复数据，还丢了一条！</span><br><span class="line">select * <span class="keyword">from</span> glon ORDER BY create_time,id limit <span class="number">0</span>, <span class="number">4</span>;</span><br><span class="line">+----+--------------+---------------------+------+</span><br><span class="line">| id | name         | create_time         | age  |</span><br><span class="line">+----+--------------+---------------------+------+</span><br><span class="line">|  <span class="number">1</span> | Eason Chan   | <span class="number">2017</span><span class="number">-05</span><span class="number">-02</span> <span class="number">08</span>:<span class="number">10</span>:<span class="number">10</span> |   <span class="number">19</span> |</span><br><span class="line">|  <span class="number">4</span> | Jacky Cheung | <span class="number">2017</span><span class="number">-05</span><span class="number">-02</span> <span class="number">14</span>:<span class="number">00</span>:<span class="number">00</span> |   <span class="number">22</span> |</span><br><span class="line">|  <span class="number">5</span> | 周芷若       | <span class="number">2017</span><span class="number">-05</span><span class="number">-02</span> <span class="number">14</span>:<span class="number">00</span>:<span class="number">00</span> |   <span class="number">16</span> |</span><br><span class="line">|  <span class="number">6</span> | Andy Lau     | <span class="number">2017</span><span class="number">-05</span><span class="number">-02</span> <span class="number">14</span>:<span class="number">00</span>:<span class="number">00</span> |   <span class="number">50</span> |</span><br><span class="line">order by 排序的时候，如果排序字段中有多行相同的列值，则排序结果是不确定的。所以后面的几组组合形式的排序或者是主键 id 的排序，因为唯一性高，所以排序是确定的，不会出现结果混乱的问题。</span><br><span class="line">最简单的方法就是在排序列（如 create time）上加索引，然后在 order by 上明示 primary key，这个问题就非常圆满的解决了。</span><br><span class="line">https:<span class="comment">//www.cnblogs.com/glon/p/6806064.html</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL-闪回工具之-binlog2sql"><a href="#MySQL-闪回工具之-binlog2sql" class="headerlink" title="MySQL 闪回工具之 binlog2sql"></a>MySQL 闪回工具之 binlog2sql</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">直接整个解析 mysql-bin<span class="number">.000001</span> 日志</span><br><span class="line"></span><br><span class="line">[root@node1 binlog2sql]# python binlog2sql.py -h127.0.0.1 -P3306 -uglon -p'123456' -dglonho -ttest --start-file='mysql-bin.000001'</span><br><span class="line">USE glonho;</span><br><span class="line">CREATE TABLE <span class="string">`test`</span> (</span><br><span class="line">  <span class="string">`id`</span> int(<span class="number">11</span>) NOT NULL AUTO_INCREMENT,</span><br><span class="line">  <span class="string">`name`</span> varchar(<span class="number">20</span>) NOT NULL,</span><br><span class="line">  <span class="string">`create_time`</span> datetime NOT NULL,</span><br><span class="line">  PRIMARY KEY (<span class="string">`id`</span>)</span><br><span class="line">) ENGINE=InnoDB DEFAULT CHARSET=utf8;</span><br><span class="line">INSERT INTO `glonho`.`test`(`create_time`, `id`, `name`) VALUES ('2012-10-01 00:00:00', 1, 'Glon Ho'); #start 547 end 772 time 2017-05-12 15:02:23</span><br><span class="line">INSERT INTO `glonho`.`test`(`create_time`, `id`, `name`) VALUES ('2016-05-02 00:00:00', 2, 'Eason Chan'); #start 547 end 772 time 2017-05-12 15:02:23</span><br><span class="line"></span><br><span class="line">[root@node1 binlog2sql]# python binlog2sql.py --flashback -h127.0.0.1 -P3306 -uglon -p'123456' -dglonho -ttest --start-file='mysql-bin.000001' --start-datetime="2017-05-12 14:57:00" --stop-datetime="2017-05-12 15:04:22"</span><br><span class="line">INSERT INTO `glonho`.`test`(`create_time`, `id`, `name`) VALUES ('2015-05-02 00:00:00', 3, 'Jacky Cheung'); #start 1164 end 1350 time 2017-05-12 15:04:03</span><br><span class="line">UPDATE `glonho`.`test` SET `create_time`='2012-10-01 00:00:00', `id`=1, `name`='Glon Ho' WHERE `create_time`='2017-05-12 00:00:00' AND `id`=1 AND `name`='Glon Ho' LIMIT 1; #start 868 end 1068 time 2017-05-12 15:03:34</span><br><span class="line"><span class="number">1</span>、在配置文件中设置了以下参数：</span><br><span class="line"></span><br><span class="line">[mysqld]</span><br><span class="line">server_id = <span class="number">1</span></span><br><span class="line">log_bin = <span class="regexp">/var/</span>log/mysql/mysql-bin.log</span><br><span class="line">max_binlog_size = <span class="number">1</span>G</span><br><span class="line">binlog_format = row</span><br><span class="line">binlog_row_image = full # 默认</span><br><span class="line"><span class="number">2</span>、在闪回的时候必须启动 MySQL 服务，因为它是通过 BINLOG_DUMP 协议来获取 binlog 内容，需要读取server端 information_schema.COLUMNS 表，来获取表结构的元信息，才能拼接成 SQL 语句。因此需要给用户提供的最小权限如下：</span><br><span class="line"></span><br><span class="line">GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO <span class="string">'user'</span>@<span class="string">'%'</span>;</span><br><span class="line">https:<span class="comment">//www.cnblogs.com/glon/p/6856192.html</span></span><br></pre></td></tr></table></figure>
<h3 id="You-can’t-specify-target-table-for-update"><a href="#You-can’t-specify-target-table-for-update" class="headerlink" title="You can’t specify target table for update"></a>You can’t specify target table for update</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">mysql不允许update目标表和子查询里面的表为同一张表</span><br><span class="line"></span><br><span class="line">错误sql：</span><br><span class="line"></span><br><span class="line">UPDATE mg_brand set <span class="string">`status`</span>=<span class="string">'0'</span> where iID=(SELECT id <span class="keyword">from</span> mg_industry where <span class="string">`name`</span>=<span class="string">'汽车'</span>) and id <span class="keyword">in</span> (SELECT id <span class="keyword">from</span> mg_brand WHERE nameC = <span class="string">'欧宝'</span> or pID = (SELECT id <span class="keyword">from</span> mg_brand WHERE nameC = <span class="string">'欧宝'</span>));</span><br><span class="line"></span><br><span class="line">解决办法：子查询sql可以改变双层的子查询，即可执行成功</span><br><span class="line"></span><br><span class="line">示例sql:</span><br><span class="line"></span><br><span class="line">UPDATE mg_brand SET <span class="string">`status`</span> = <span class="string">'0'</span> WHERE iID = ( SELECT id FROM mg_industry WHERE <span class="string">`name`</span> = <span class="string">'汽车'</span> ) AND id IN ( SELECT id FROM (SELECT id FROM mg_brand) AS temp WHERE nameC = <span class="string">'欧宝'</span> OR pID = ( SELECT id FROM ( SELECT id FROM mg_brand WHERE nameC = <span class="string">'欧宝'</span> ) AS te WHERE <span class="number">1</span> ));</span><br></pre></td></tr></table></figure>
<h3 id="分组无数据查询填充0"><a href="#分组无数据查询填充0" class="headerlink" title="分组无数据查询填充0"></a>分组无数据查询填充0</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line">select date(t.create_time) <span class="keyword">as</span> <span class="string">`date`</span>,</span><br><span class="line">       count(t.id)  <span class="keyword">as</span> num</span><br><span class="line"><span class="keyword">from</span> t_user t</span><br><span class="line">group by <span class="string">`date`</span>;</span><br><span class="line">select * <span class="keyword">from</span> (SELECT DATE_FORMAT(DATE_SUB(<span class="string">'2019-05-09'</span>, INTERVAL xc day), <span class="string">'%Y-%m-%d'</span>) <span class="keyword">as</span> day</span><br><span class="line">      FROM (SELECT @xi := @xi + <span class="number">1</span> <span class="keyword">as</span> xc</span><br><span class="line">             <span class="keyword">from</span> (SELECT <span class="number">1</span> UNION SELECT <span class="number">2</span> UNION SELECT <span class="number">3</span> UNION SELECT <span class="number">4</span> UNION SELECT <span class="number">5</span>) xc1,</span><br><span class="line">                  (SELECT <span class="number">1</span> UNION SELECT <span class="number">2</span> UNION SELECT <span class="number">3</span> UNION SELECT <span class="number">4</span> UNION SELECT <span class="number">5</span>) xc2,</span><br><span class="line">                  (SELECT <span class="number">1</span> UNION SELECT <span class="number">2</span> UNION SELECT <span class="number">3</span> UNION SELECT <span class="number">4</span> UNION SELECT <span class="number">5</span>) xc3,</span><br><span class="line">                  (SELECT @xi := <span class="number">-1</span>) xc0</span><br><span class="line">           ) <span class="keyword">as</span> t) <span class="keyword">as</span> t2</span><br><span class="line">					 where t2.<span class="string">`day`</span> &gt; <span class="string">'2019-05-02'</span> and t2.<span class="string">`day`</span> &lt;= <span class="string">'2019-05-09'</span></span><br><span class="line">select t2.<span class="string">`day`</span> <span class="keyword">as</span> <span class="string">`date`</span>, count(t.id) <span class="keyword">as</span> num</span><br><span class="line"><span class="keyword">from</span> (SELECT DATE_FORMAT(DATE_SUB(<span class="string">'2019-05-09'</span>, INTERVAL xc day), <span class="string">'%Y-%m-%d'</span>) <span class="keyword">as</span> day</span><br><span class="line">      FROM (</span><br><span class="line">             SELECT @xi := @xi + <span class="number">1</span> <span class="keyword">as</span> xc</span><br><span class="line">             <span class="keyword">from</span> (SELECT <span class="number">1</span> UNION SELECT <span class="number">2</span> UNION SELECT <span class="number">3</span> UNION SELECT <span class="number">4</span> UNION SELECT <span class="number">5</span>) xc1,</span><br><span class="line">                  (SELECT <span class="number">1</span> UNION SELECT <span class="number">2</span> UNION SELECT <span class="number">3</span> UNION SELECT <span class="number">4</span> UNION SELECT <span class="number">5</span>) xc2,</span><br><span class="line">                  (SELECT <span class="number">1</span> UNION SELECT <span class="number">2</span> UNION SELECT <span class="number">3</span> UNION SELECT <span class="number">4</span> UNION SELECT <span class="number">5</span>) xc3,</span><br><span class="line">                  (SELECT @xi := <span class="number">-1</span>) xc0</span><br><span class="line">           ) <span class="keyword">as</span> x1x2x) t2</span><br><span class="line">       left join t_user t on date(t.create_time) = t2.day</span><br><span class="line">where t2.<span class="string">`day`</span> &gt; <span class="string">'2019-05-02'</span> and t2.<span class="string">`day`</span> &lt;= <span class="string">'2019-05-09'</span></span><br><span class="line">group by date ORDER BY date asc;</span><br><span class="line"></span><br><span class="line">+------------+-----+</span><br><span class="line">|    date    | num |</span><br><span class="line">+------------+-----+</span><br><span class="line">| <span class="number">2019</span><span class="number">-05</span><span class="number">-03</span> |  <span class="number">0</span>  |</span><br><span class="line">+------------+-----+</span><br><span class="line">| <span class="number">2019</span><span class="number">-05</span><span class="number">-04</span> |  <span class="number">0</span>  |</span><br><span class="line">+------------+-----+</span><br><span class="line">| <span class="number">2019</span><span class="number">-05</span><span class="number">-05</span> |  <span class="number">0</span>  |</span><br><span class="line">+------------+-----+</span><br><span class="line">| <span class="number">2019</span><span class="number">-05</span><span class="number">-06</span> |  <span class="number">2</span>  |</span><br><span class="line">+------------+-----+</span><br><span class="line">| <span class="number">2019</span><span class="number">-05</span><span class="number">-07</span> |  <span class="number">0</span>  |</span><br><span class="line">+------------+-----+</span><br><span class="line">| <span class="number">2019</span><span class="number">-05</span><span class="number">-08</span> |  <span class="number">2</span>  |</span><br><span class="line">+------------+-----+</span><br><span class="line">| <span class="number">2019</span><span class="number">-05</span><span class="number">-09</span> |  <span class="number">9</span>  |</span><br><span class="line">+------------+-----+</span><br><span class="line">http:<span class="comment">//nullpointer.pw/Mysql%E6%97%A5%E6%9C%9F%E5%88%86%E7%BB%84%E6%97%A0%E6%95%B0%E6%8D%AE%E6%9F%A5%E8%AF%A2%E5%A1%AB%E5%85%850.html</span></span><br></pre></td></tr></table></figure>
<h3 id="保留-IN-中的顺序"><a href="#保留-IN-中的顺序" class="headerlink" title="保留 IN 中的顺序"></a>保留 IN 中的顺序</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">SELECT * FROM <span class="string">`user_temporary`</span> WHERE ( <span class="string">`id`</span> IN (<span class="string">'29500'</span>,<span class="string">'29582'</span>,<span class="string">'29583'</span>,<span class="string">'28299'</span>) ) LIMIT <span class="number">0</span>, <span class="number">20</span>;</span><br><span class="line">SELECT * FROM <span class="string">`user_temporary`</span> WHERE ( <span class="string">`id`</span> IN (<span class="string">'29500'</span>,<span class="string">'29582'</span>,<span class="string">'29583'</span>,<span class="string">'28299'</span><span class="string">') ) ORDER BY field(id,29500,29582,29583,28299) LIMIT 0, 20;</span></span><br></pre></td></tr></table></figure>
<h3 id="分组取前3"><a href="#分组取前3" class="headerlink" title="分组取前3"></a>分组取前3</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line">cs_goods 表结构</span><br><span class="line"></span><br><span class="line">id	goods_id	cs_merchant_id	created_at</span><br><span class="line"><span class="number">1</span>	<span class="number">234</span>	<span class="number">3</span>	<span class="number">2019</span><span class="number">-07</span><span class="number">-09</span> <span class="number">19</span>:<span class="number">45</span>:<span class="number">33</span></span><br><span class="line"><span class="number">2</span>	<span class="number">33</span>	<span class="number">3</span>	<span class="number">2019</span><span class="number">-07</span><span class="number">-10</span> <span class="number">19</span>:<span class="number">45</span>:<span class="number">33</span></span><br><span class="line"><span class="number">3</span>	<span class="number">44</span>	<span class="number">3</span>	<span class="number">2019</span><span class="number">-07</span><span class="number">-11</span> <span class="number">19</span>:<span class="number">45</span>:<span class="number">33</span></span><br><span class="line"><span class="number">4</span>	<span class="number">55</span>	<span class="number">3</span>	<span class="number">2019</span><span class="number">-07</span><span class="number">-01</span> <span class="number">19</span>:<span class="number">45</span>:<span class="number">33</span></span><br><span class="line"><span class="number">5</span>	<span class="number">33</span>	<span class="number">5</span>	<span class="number">2019</span><span class="number">-07</span><span class="number">-02</span> <span class="number">19</span>:<span class="number">45</span>:<span class="number">33</span></span><br><span class="line"><span class="number">6</span>	<span class="number">44</span>	<span class="number">5</span>	<span class="number">2019</span><span class="number">-07</span><span class="number">-08</span> <span class="number">19</span>:<span class="number">45</span>:<span class="number">33</span></span><br><span class="line"><span class="number">7</span>	<span class="number">55</span>	<span class="number">6</span>	<span class="number">2019</span><span class="number">-07</span><span class="number">-06</span> <span class="number">19</span>:<span class="number">45</span>:<span class="number">33</span></span><br><span class="line">需求：获取 cs_goods 表中的所有商品，但同一个超市最多只能出现 <span class="number">3</span> 个商品（cs_merchant_id 是超市 id），并用 created_at 进行倒序排列，最后的结果应该是 <span class="number">3</span> <span class="number">2</span> <span class="number">1</span> <span class="number">6</span> <span class="number">7</span> <span class="number">5</span></span><br><span class="line"></span><br><span class="line"> https:<span class="comment">//learnku.com/laravel/t/31355</span></span><br><span class="line"></span><br><span class="line">原生sql：</span><br><span class="line">SELECT a.* FROM cs_goods a WHERE ( SELECT COUNT(*) FROM cs_goods WHERE cs_merchant_id = a.cs_merchant_id AND id &gt; a.id ) &lt; <span class="number">3</span> ORDER BY a.created_at desc;</span><br><span class="line">SELECT</span><br><span class="line"><span class="string">`a`</span>.* </span><br><span class="line">FROM</span><br><span class="line"><span class="string">`cs_goods`</span> AS <span class="string">`a`</span> </span><br><span class="line">WHERE</span><br><span class="line">( SELECT COUNT(<span class="string">`b`</span>.<span class="string">`id`</span>)  FROM <span class="string">`cs_goods`</span> AS b WHERE <span class="string">`b`</span>.<span class="string">`cs_merchant_id`</span> = <span class="string">`a`</span>.<span class="string">`cs_merchant_id`</span> AND <span class="string">`b`</span>.<span class="string">`created_at`</span> &gt; <span class="string">`a`</span>.<span class="string">`created_at`</span> ) &lt; <span class="number">3</span> </span><br><span class="line">ORDER BY</span><br><span class="line"><span class="string">`a`</span>.<span class="string">`created_at`</span> DESC;</span><br><span class="line">SELECT</span><br><span class="line"><span class="string">`a`</span>.* </span><br><span class="line">FROM</span><br><span class="line"><span class="string">`cs_goods`</span> AS <span class="string">`a`</span></span><br><span class="line">LEFT JOIN <span class="string">`cs_goods`</span> AS <span class="string">`b`</span> ON <span class="string">`a`</span>.<span class="string">`cs_merchant_id`</span> = <span class="string">`b`</span>.<span class="string">`cs_merchant_id`</span> </span><br><span class="line">AND <span class="string">`b`</span>.<span class="string">`created_at`</span> &gt; <span class="string">`a`</span>.<span class="string">`created_at`</span> </span><br><span class="line">GROUP BY</span><br><span class="line"><span class="string">`a`</span>.<span class="string">`id`</span> </span><br><span class="line">HAVING</span><br><span class="line">COUNT( b.id ) &lt; <span class="number">3</span> </span><br><span class="line">ORDER BY</span><br><span class="line"><span class="string">`a`</span>.<span class="string">`created_at`</span> DESC</span><br><span class="line"></span><br><span class="line"> \DB::table(<span class="string">'cs_goods as a'</span>)</span><br><span class="line">        -&gt;select(<span class="string">'a.*'</span>)</span><br><span class="line">        -&gt;leftJoin(<span class="string">'cs_goods as b'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">$join</span>)</span>&#123;</span><br><span class="line">            <span class="keyword">return</span> $join-&gt;on(<span class="string">'a.cs_merchant_id'</span>,<span class="string">'='</span>,<span class="string">'b.cs_merchant_id'</span>)</span><br><span class="line">                -&gt;on(<span class="string">'b.created_at'</span>,<span class="string">'&gt;'</span>,<span class="string">'a.created_at'</span>);</span><br><span class="line">        &#125;)</span><br><span class="line">        -&gt;groupBy(<span class="string">'a.id'</span>)</span><br><span class="line">        -&gt;havingRaw(<span class="string">'COUNT(b.id) &lt; 3'</span>)</span><br><span class="line">        -&gt;orderByDesc(<span class="string">'a.created_at'</span>)</span><br><span class="line">        -&gt;toSql();</span><br></pre></td></tr></table></figure>
<h3 id="升级mongodb3"><a href="#升级mongodb3" class="headerlink" title="升级mongodb3"></a>升级mongodb3</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">Server at <span class="number">10.23</span><span class="number">.2</span><span class="number">.1</span>:<span class="number">27017</span> reports wire version <span class="number">2</span>, but <span class="keyword">this</span> version <span class="keyword">of</span> libmongoc requires at least <span class="number">3</span> (MongoDB <span class="number">3.0</span>)   </span><br><span class="line"></span><br><span class="line">https:<span class="comment">//segmentfault.com/a/1190000004547368</span></span><br><span class="line">curl https:<span class="comment">//fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.9.tgz  </span></span><br><span class="line"></span><br><span class="line">tar -xvzf mongodb-linux-x86_64<span class="number">-3.0</span><span class="number">.9</span>.tgz  </span><br><span class="line">cd mongodb-linux-x86_64<span class="number">-3.0</span><span class="number">.9</span></span><br><span class="line">[root@localhost ~]# ps aux|grep mongo</span><br><span class="line">root      <span class="number">6217</span>  <span class="number">0.2</span>  <span class="number">0.3</span> <span class="number">4773512</span> <span class="number">37412</span> ?       Sl   May06 <span class="number">232</span>:<span class="number">35</span> mongod --fork --dbpath=<span class="regexp">/data2/m</span>ongodb --logpath=<span class="regexp">/data2/m</span>ongodb/mongodb.log --logappend</span><br><span class="line">root     <span class="number">28665</span>  <span class="number">0.0</span>  <span class="number">0.0</span> <span class="number">103256</span>   <span class="number">844</span> pts/<span class="number">1</span>    S+   <span class="number">16</span>:<span class="number">19</span>   <span class="number">0</span>:<span class="number">00</span> grep mongo</span><br><span class="line">[root@localhost ~]# kill -9 6217</span><br><span class="line">[root@localhost ~]# /data1/projects/mongodb-linux-x86_64-3.0.9/bin/mongod --fork --dbpath=/data2/mongodb --logpath=/data2/mongodb/mongodb.log --logappend</span><br><span class="line">about to fork child process, waiting until server is ready <span class="keyword">for</span> connections.</span><br><span class="line">forked process: <span class="number">29713</span></span><br><span class="line">child process started successfully, parent exiting</span><br><span class="line">[root@localhost ~]# /data1/projects/mongodb-linux-x86_64-3.0.9/bin/mongo</span><br><span class="line">MongoDB shell version: <span class="number">3.0</span><span class="number">.6</span></span><br><span class="line">connecting to: test</span><br><span class="line">Server has startup warnings:</span><br></pre></td></tr></table></figure>
<h3 id="Mysql-大表分页查询优化"><a href="#Mysql-大表分页查询优化" class="headerlink" title="Mysql 大表分页查询优化"></a>Mysql 大表分页查询优化</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">select id, content <span class="keyword">from</span> table_name where status = <span class="number">1</span> order by id asc limit <span class="number">1328000</span>, <span class="number">1000</span></span><br><span class="line">执行了 <span class="number">90</span> 秒，扫描了 <span class="number">1329172</span> 行。</span><br><span class="line"></span><br><span class="line">改写成</span><br><span class="line"></span><br><span class="line">select a2.id, a2.content <span class="keyword">from</span> (select id <span class="keyword">from</span> table_name where status = <span class="number">1</span> order by id asc limit <span class="number">1328000</span>, <span class="number">1000</span>) a1, table_name a2 where a1.id=a2.id;</span><br><span class="line"></span><br><span class="line">SELECT * FROM table_name a1 INNER JOIN (SELECT id FROM table_name ORDER BY id LIMIT <span class="number">1328000</span>,<span class="number">1000</span>) a2 ON a1.id=a2.id</span><br><span class="line">select id <span class="keyword">from</span> table_name where id&gt;<span class="number">73575000</span> order by id asc limit <span class="number">0</span>, <span class="number">5000</span></span><br><span class="line">执行时间<span class="number">19.63</span>ms</span><br><span class="line"></span><br><span class="line">select a2.id,a2.keyword,a2.url <span class="keyword">from</span> (select id <span class="keyword">from</span> table_name where id&gt;<span class="number">73575000</span> order by id asc limit <span class="number">0</span>, <span class="number">5000</span>) a1, table_name a2 where a1.id=a2.id</span><br><span class="line">执行时间<span class="number">26.35</span>ms，又可以愉快的玩耍了。</span><br><span class="line"></span><br><span class="line">或者直接</span><br><span class="line"></span><br><span class="line">select id,keyword,url  <span class="keyword">from</span> table_name where id&gt;<span class="number">73575000</span> order by id asc limit <span class="number">0</span>, <span class="number">5000</span></span><br><span class="line"></span><br><span class="line">https:<span class="comment">//mengkang.net/1300.html</span></span><br></pre></td></tr></table></figure>
<h3 id="不区分大小写"><a href="#不区分大小写" class="headerlink" title="不区分大小写"></a>不区分大小写</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">insert into tableName(date,workflow,cou) values(<span class="string">'2019-01-04'</span>,<span class="string">'tx'</span>,<span class="number">10000</span>);</span><br><span class="line">insert into tableName(date,workflow,cou) values(<span class="string">'2019-01-04'</span>,<span class="string">'Tx'</span>,<span class="number">100000</span>);</span><br><span class="line"></span><br><span class="line">alter table statistic_daily_workflow_count modify column workflow varchar(<span class="number">170</span>) binary character set utf8 collate utf8_bin;</span><br><span class="line">创建表时字段指定binary</span><br><span class="line">create table PlainText(</span><br><span class="line">Content nvarchar(<span class="number">50</span>) binary,</span><br><span class="line">primary key(Content)</span><br><span class="line">);</span><br><span class="line">修改列指定binary</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line">-- 修改列</span><br><span class="line">ALTER TABLE <span class="string">`Md5Data`</span>.<span class="string">`PlainText`</span> </span><br><span class="line">CHANGE COLUMN <span class="string">`Content`</span> <span class="string">`Content`</span> VARCHAR(<span class="number">55</span>) CHARACTER SET <span class="string">'utf8'</span> BINARY NOT NULL DEFAULT <span class="string">''</span> ;</span><br><span class="line"></span><br><span class="line">select * <span class="keyword">from</span> usertable where binary id = <span class="string">'A'</span>;</span><br><span class="line">http:<span class="comment">//www.ikeguang.com/2019/01/05/mysql-unique/</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL-备份"><a href="#MySQL-备份" class="headerlink" title="MySQL 备份"></a>MySQL 备份</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">[root@localhost mc_orderdb]# mysqldump -ubackup -p --master-data=2 --single-transaction --routines --triggers --events  --tab="/tmp/mc_orderdb"  mc_orderdb</span><br><span class="line">Enter password: </span><br><span class="line"></span><br><span class="line">--</span><br><span class="line">-- Position to start replication or point-<span class="keyword">in</span>-time recovery <span class="keyword">from</span></span><br><span class="line">--</span><br><span class="line"></span><br><span class="line">-- CHANGE MASTER TO MASTER_LOG_FILE=<span class="string">'mysql_bin.000009'</span>, MASTER_LOG_POS=<span class="number">1095</span>;</span><br><span class="line">mysqldump: Got error: <span class="number">1</span>: Can<span class="string">'t create/write to file '</span>/tmp/mc_orderdb/order_cart.txt<span class="string">' (Errcode: 13 - Permission denied) when executing '</span>SELECT INTO OUTFILE<span class="string">'</span></span><br><span class="line"><span class="string">1. 权限问题：chown mysql:mysql mc_orderdb/</span></span><br><span class="line"><span class="string">2. 关闭防火墙selinux</span></span><br><span class="line"><span class="string">　shell&gt;vi /etc/selinux/config</span></span><br><span class="line"><span class="string">           SELINUX=disabled</span></span><br><span class="line"><span class="string">3. shell&gt;setsebool -P mysqld_disable_trans=1</span></span><br></pre></td></tr></table></figure>
<h3 id="groupBy-分组统计"><a href="#groupBy-分组统计" class="headerlink" title="groupBy 分组统计"></a>groupBy 分组统计</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line">数据中 <span class="number">4</span> 号～<span class="number">7</span> 号的时间段没有返回，我们理想中的返回格式是补全没有的日期，然后在这个日期对应的数量字段填 <span class="number">0</span>。</span><br><span class="line"></span><br><span class="line">在网上 google 了一下，解决方案是新建一张自期表做主表，左联要统计的表，</span><br><span class="line"></span><br><span class="line">CREATE TABLE num (i int);-- 创建一个表用来储存<span class="number">0</span><span class="number">-9</span>的数字</span><br><span class="line">INSERT INTO num (i) VALUES (<span class="number">0</span>), (<span class="number">1</span>), (<span class="number">2</span>), (<span class="number">3</span>), (<span class="number">4</span>), (<span class="number">5</span>), (<span class="number">6</span>), (<span class="number">7</span>), (<span class="number">8</span>), (<span class="number">9</span>);-- 生成<span class="number">0</span><span class="number">-9</span>的数字，方便以后计算时间</span><br><span class="line"></span><br><span class="line">CREATE TABLE  <span class="keyword">if</span> not exists calendar(datelist date); -- 生成一个存储日期的表，datalist是字段名</span><br><span class="line"></span><br><span class="line">-- 这里是生成并插入日期数据</span><br><span class="line">INSERT INTO calendar(datelist) SELECT</span><br><span class="line">    adddate(</span><br><span class="line">        (   -- 这里的起始日期，你可以换成当前日期</span><br><span class="line">            DATE_FORMAT(<span class="string">"2016-1-1"</span>, <span class="string">'%Y-%m-%d'</span>) </span><br><span class="line">        ),</span><br><span class="line">        numlist.id</span><br><span class="line">    ) AS <span class="string">`date`</span></span><br><span class="line">FROM</span><br><span class="line">    (</span><br><span class="line">        SELECT</span><br><span class="line">            n1.i + n10.i * <span class="number">10</span> + n100.i * <span class="number">100</span> + n1000.i * <span class="number">1000</span>+ n10000.i * <span class="number">10000</span> AS id</span><br><span class="line">        FROM</span><br><span class="line">            num n1</span><br><span class="line">        CROSS JOIN num AS n10</span><br><span class="line">        CROSS JOIN num AS n100</span><br><span class="line">        CROSS JOIN num AS n1000</span><br><span class="line">        CROSS JOIN num AS n10000</span><br><span class="line">    ) AS numlist;</span><br><span class="line">运行 sql 语句后，请删除 num 表</span><br><span class="line">数据库在通过连接两张或多张表来返回记录时，都会生成一张中间的临时表，然后再将这张临时表返回给用户；</span><br><span class="line"></span><br><span class="line">where 条件是在临时表生成好后，再对临时表进行过滤的条件；</span><br><span class="line"></span><br><span class="line">因此：where 条件加上，已经没有 left join 的含义（必须返回左边表的记录）了，条件不为真的就全部过滤掉。</span><br><span class="line"></span><br><span class="line">解决方案是把限制条件放在 on 后面</span><br><span class="line"></span><br><span class="line">select a.*,b.*</span><br><span class="line"><span class="keyword">from</span> table1 a</span><br><span class="line">left join table2 b on b.X=a.X and XXX</span><br><span class="line">结论：</span><br><span class="line"></span><br><span class="line">where 后面：是先连接然生成临时查询结果，然后再筛选</span><br><span class="line"></span><br><span class="line">on 后面：先根据条件过滤筛选，再连 生成临时查询结果https:<span class="comment">//learnku.com/articles/26796</span></span><br></pre></td></tr></table></figure>
<h3 id="导入文件"><a href="#导入文件" class="headerlink" title="导入文件"></a>导入文件</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">修改 my.cnf [mac]，my.ini.[win],</span><br><span class="line">secure-file-priv=<span class="string">'txt 文本存放的目录'</span></span><br><span class="line">重启 mysql</span><br><span class="line">\t 是 txt 文本中的字段区分，\n 是文本行的结尾，sys_log20190731 表名</span><br><span class="line"><span class="number">80000000.</span>txt 要放到你给权限的目录的下，secure-file-priv=<span class="string">'txt 文本存放的目录'</span></span><br><span class="line">load data infile <span class="string">'mypath/80000000.txt'</span> ignore into table sys_log20190731 character set gbk fields terminated by <span class="string">'\t'</span> enclosed by <span class="string">'"'</span> lines terminated by <span class="string">'\n'</span> (<span class="string">`field1`</span>,<span class="string">`field2`</span>,<span class="string">`field3`</span>,<span class="string">`field4`</span>,<span class="string">`field5`</span>,<span class="string">`field6`</span>,<span class="string">`field7`</span>);</span><br><span class="line">https:<span class="comment">//learnku.com/articles/31979</span></span><br></pre></td></tr></table></figure>
<h3 id="关联查询"><a href="#关联查询" class="headerlink" title="关联查询"></a>关联查询</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line">内连接分为三类</span><br><span class="line">    - 等值连接：on a.id = b.id</span><br><span class="line">    - 不等值连接：on a.id &gt; b.id</span><br><span class="line">    - 自连接：select * <span class="keyword">from</span> a t1 inner join a t2 on t1.id = t2.id</span><br><span class="line">  <span class="comment">//创建student表，并插入测试数据</span></span><br><span class="line">  create table student(</span><br><span class="line">  id int unsigned primary key auto_increment,</span><br><span class="line">  name char(<span class="number">10</span>) not <span class="literal">null</span></span><br><span class="line">  );</span><br><span class="line">  insert into student(name) values(<span class="string">'小明'</span>),(<span class="string">'小红'</span>);</span><br><span class="line">  <span class="comment">//创建course表，并插入测试数据</span></span><br><span class="line">  create table course(</span><br><span class="line">  id int unsigned primary key auto_increment,</span><br><span class="line">  name char(<span class="number">20</span>) not <span class="literal">null</span></span><br><span class="line">  );</span><br><span class="line">  insert into course(name) values(<span class="string">'PHP'</span>),(<span class="string">'JAVA'</span>);</span><br><span class="line">  <span class="comment">//创建student_course表，并插入测试数据</span></span><br><span class="line">  create table student_course(</span><br><span class="line">  sid int unsigned,</span><br><span class="line">  cid int unsigned,</span><br><span class="line">  score int unsigned not <span class="literal">null</span>,</span><br><span class="line">  foreign key (sid) references student(id),</span><br><span class="line">  foreign key (cid) references course(id),</span><br><span class="line">  primary key(sid, cid)</span><br><span class="line">  );</span><br><span class="line">  insert into student_course values(<span class="number">1</span>,<span class="number">1</span>,<span class="number">80</span>),(<span class="number">1</span>,<span class="number">2</span>,<span class="number">90</span>),(<span class="number">2</span>,<span class="number">1</span>,<span class="number">90</span>),(<span class="number">2</span>,<span class="number">2</span>,<span class="number">70</span>);  </span><br><span class="line">    查询 student 表中重名的学生，结果包含 id 和 name，按 name 升序</span><br><span class="line">    </span><br><span class="line">    select id,name</span><br><span class="line">    <span class="keyword">from</span> student</span><br><span class="line">    where name <span class="keyword">in</span> (</span><br><span class="line">    select name <span class="keyword">from</span> student group by name having(count(*) &gt; <span class="number">1</span>)</span><br><span class="line">    ) order by name ASC;</span><br><span class="line">    查询每个学生的总成绩，结果列出学生姓名和总成绩。</span><br><span class="line">    </span><br><span class="line">    select name,sum(score)</span><br><span class="line">    <span class="keyword">from</span> student left join student_course</span><br><span class="line">    on student.id=student_course.sid</span><br><span class="line">    group by sid;</span><br><span class="line">    +------+------------+</span><br><span class="line">    | name | sum(score) |</span><br><span class="line">    +------+------------+</span><br><span class="line">    | ???  |        <span class="number">170</span> |</span><br><span class="line">    | ??   |        <span class="number">160</span> |</span><br><span class="line">    </span><br><span class="line">    在 student_course 表查询各科成绩最高的学生，结果列出学生 id、课程 id 和对应的成绩</span><br><span class="line">    </span><br><span class="line">    select * <span class="keyword">from</span> student_course <span class="keyword">as</span> x where score&gt;=</span><br><span class="line">    (select max(score) <span class="keyword">from</span> student_course <span class="keyword">as</span> y where cid=x.cid);</span><br><span class="line">    +-----+-----+-------+</span><br><span class="line">    | sid | cid | score |</span><br><span class="line">    +-----+-----+-------+</span><br><span class="line">    |   <span class="number">1</span> |   <span class="number">2</span> |    <span class="number">90</span> |</span><br><span class="line">    |   <span class="number">2</span> |   <span class="number">1</span> |    <span class="number">90</span> |</span><br><span class="line">    +-----+-----+-------+</span><br><span class="line">    在 student_course 表中查询每门课成绩都不低于 <span class="number">80</span> 的学生 id</span><br><span class="line">    </span><br><span class="line">    select distinct sid</span><br><span class="line">    <span class="keyword">from</span> student_course</span><br><span class="line">    where sid not <span class="keyword">in</span> (</span><br><span class="line">    select sid <span class="keyword">from</span> student_course</span><br><span class="line">    where score &lt; <span class="number">80</span>);</span><br><span class="line">    +-----+</span><br><span class="line">    | sid |</span><br><span class="line">    +-----+</span><br><span class="line">    |   <span class="number">1</span> |</span><br><span class="line">    +-----+</span><br><span class="line">    https:<span class="comment">//learnku.com/articles/32039</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL大数据分页"><a href="#MySQL大数据分页" class="headerlink" title="MySQL大数据分页"></a>MySQL大数据分页</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">SELECT * FROM test where status = <span class="number">1</span> limit start, <span class="number">1000</span></span><br><span class="line">select * <span class="keyword">from</span> test a , </span><br><span class="line">    (select id <span class="keyword">from</span> test where status = <span class="number">1</span> limit <span class="number">300000</span>, <span class="number">10</span>) b </span><br><span class="line">    where a.id  = b.id;</span><br><span class="line">---</span><br><span class="line"><span class="number">10</span> rows <span class="keyword">in</span> set (<span class="number">0.06</span> sec)</span><br><span class="line">select * <span class="keyword">from</span> test </span><br><span class="line">    inner join (select id <span class="keyword">from</span> test  limit <span class="number">300000</span>, <span class="number">10</span>) t2 </span><br><span class="line">    using (id);</span><br><span class="line">---</span><br><span class="line"><span class="number">10</span> rows <span class="keyword">in</span> set (<span class="number">0.06</span> sec)</span><br><span class="line">select * <span class="keyword">from</span> test </span><br><span class="line">    where status = <span class="number">1</span> and id &gt; xxx</span><br><span class="line">    order by id asc</span><br><span class="line">    limit <span class="number">10</span></span><br><span class="line">---</span><br><span class="line"><span class="number">10</span> rows <span class="keyword">in</span> set (<span class="number">0.00</span> sec)</span><br><span class="line">https:<span class="comment">//blog.jiaojie.site/_posts/2017/12/22/mysql-pagination-tips/</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL-索引使用策略及优化"><a href="#MySQL-索引使用策略及优化" class="headerlink" title="MySQL 索引使用策略及优化"></a>MySQL 索引使用策略及优化</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">MySQL 的优化主要分为结构优化（Scheme optimization）和查询优化（Query optimization）。</span><br><span class="line">从 https:<span class="comment">//github.com/datacharmer/test_db 倒入 employees.sql 文件</span></span><br><span class="line">EXPLAIN 出来的信息有 <span class="number">10</span> 列，分别是 id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra</span><br><span class="line">概要描述：</span><br><span class="line"></span><br><span class="line">id: 选择标识符</span><br><span class="line">select_type: 表示查询的类型。</span><br><span class="line">table: 输出结果集的表</span><br><span class="line">type: 表示表的连接类型</span><br><span class="line">all（全表扫描） 、index（按照索引顺序的全表扫描）、range (有范围的索引扫描)</span><br><span class="line">req (查找条件列使用了索引而且不为主键和 unique, 使用该索引列的值并不唯一)、ref_eq（使用了主键或者唯一性索引进行查找的情况）、</span><br><span class="line"><span class="keyword">const</span>（主键放置到 where 后面作为条件查询，mysql 优化器就能把这次查询优化转化为一个常量）</span><br><span class="line">possible_keys: 表示查询时，可能使用的索引</span><br><span class="line">key: 表示实际使用的索引</span><br><span class="line">key_len: 索引字段的长度</span><br><span class="line">ref: 列与索引的比较</span><br><span class="line">rows: 扫描出的行数 (估算的行数)</span><br><span class="line">Extra: 执行情况的描述和说明</span><br><span class="line"></span><br><span class="line">不建议建索引的情况是索引的选择性较低。所谓索引的选择性（Selectivity），是指不重复的索引值（也叫基数，Cardinality）与表记录数（#T）的比值：</span><br><span class="line"></span><br><span class="line">Index Selectivity = Cardinality / #T</span><br><span class="line">显然选择性的取值范围为 (<span class="number">0</span>, <span class="number">1</span>]，选择性越高的索引价值越大，这是由 B+Tree 的性质决定的</span><br><span class="line">select count(distinct title)/count(*) <span class="keyword">from</span> table ; https:<span class="comment">//learnku.com/articles/32225</span></span><br></pre></td></tr></table></figure>
<h3 id="datetime-默认值为‘0000-00-00-00-00-00’值无法创建"><a href="#datetime-默认值为‘0000-00-00-00-00-00’值无法创建" class="headerlink" title="datetime 默认值为‘0000-00-00 00:00:00’值无法创建"></a>datetime 默认值为‘0000-00-00 00:00:00’值无法创建</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">使用root登陆数据库 命令界面执行</span><br><span class="line">select @@sql_mode;</span><br><span class="line"> 结果中包含下面两个</span><br><span class="line">NO_ZERO_IN_DATE,NO_ZERO_DATE</span><br><span class="line"><span class="number">2</span>、修改/etc/my.cnf，查找sql_model如果找不到则添加如下代码 </span><br><span class="line">sql_mode=<span class="string">"ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"</span></span><br><span class="line"><span class="number">3</span>、重启mysql</span><br><span class="line">/etc/ini.d/mysql restart</span><br><span class="line">简单几步大功告成！</span><br><span class="line"> </span><br><span class="line">原因：</span><br><span class="line">NO_ZERO_IN_DATE,NO_ZERO_DATE是无法默认为‘<span class="number">0000</span><span class="number">-00</span><span class="number">-00</span> <span class="number">00</span>:<span class="number">00</span>:<span class="number">00</span>’的根源。</span><br><span class="line">NO_ZERO_IN_DATE：在严格模式下，不允许日期和月份为零 </span><br><span class="line">NO_ZERO_DATE：设置该值，mysql数据库不允许插入零日期，插入零日期会抛出错误而不是警告。</span><br></pre></td></tr></table></figure>
<h3 id="删除重复数据"><a href="#删除重复数据" class="headerlink" title="删除重复数据"></a>删除重复数据</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">select *<span class="keyword">from</span> hso_min WHERE id not IN (SELECT bid FROM (SELECT min(id) <span class="keyword">as</span> bid FROM hso_min where symbol=<span class="string">'xau'</span> and uts&gt;<span class="number">1565971200</span>  GROUP BY min)<span class="keyword">as</span> b) and symbol=<span class="string">'xau'</span> and uts&gt;<span class="number">1565971200</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">delete</span> <span class="keyword">from</span> hso_min WHERE id not IN (SELECT bid FROM (SELECT min(id) <span class="keyword">as</span> bid FROM hso_min where symbol=<span class="string">'xau'</span> and uts&gt;<span class="number">1565971200</span>  GROUP BY min)<span class="keyword">as</span> b) and symbol=<span class="string">'xau'</span> and uts&gt;<span class="number">1565971200</span>;</span><br></pre></td></tr></table></figure>
<h3 id="每个用户最新一条"><a href="#每个用户最新一条" class="headerlink" title="每个用户最新一条"></a>每个用户最新一条</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">表一 messages</span><br><span class="line"></span><br><span class="line">id (PRIMARY KEY)、to_user_id、from_user_id、content、created_at</span><br><span class="line">表二 user</span><br><span class="line"></span><br><span class="line">id (PRIMARY KEY)、name、created_at</span><br><span class="line">查询当天最新的 messages 并分页，要求同 user 只取一条 messages</span><br><span class="line"></span><br><span class="line">group by 执行在 order by 之前，order by 只是对group by 结果进行排序。可以参考类似文章https:<span class="comment">//blog.csdn.net/zcd3f/article/details/84767206</span></span><br><span class="line">SELECT max(created_at),from_user_id,content <span class="keyword">from</span> messages WHERE created_at like <span class="string">"%2019-08-21%"</span> GROUP BY from_user_id ORDER BY from_user_id desc limit <span class="number">100</span>;</span><br><span class="line">DB::table(<span class="string">'messages as t1'</span>)</span><br><span class="line">  -&gt;leftJoin(<span class="string">'messages as t2'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">$join</span>) </span>&#123;</span><br><span class="line">    $join-&gt;on(<span class="string">'t1.from_user_id'</span>, <span class="string">'='</span>, <span class="string">'t2.from_user_id'</span>)-&gt;on(<span class="string">'t1.id'</span>, <span class="string">'&lt;'</span>, <span class="string">'t2.id'</span>);</span><br><span class="line">&#125;)</span><br><span class="line">  -&gt;leftJoin(<span class="string">'user as t3'</span>, <span class="string">'t1.from_user_id'</span>, <span class="string">'='</span>, <span class="string">'t3.id'</span>)</span><br><span class="line">  -&gt;where(<span class="string">'t1.to_user_id'</span>, $id)</span><br><span class="line">  -&gt;whereNull(<span class="string">'t2.id'</span>)-&gt;paginate(<span class="number">15</span>);</span><br><span class="line">https:<span class="comment">//learnku.com/articles/32919 </span></span><br><span class="line">需要查询表里不同分类下的order最大的记录</span><br><span class="line">SELECT id,tid,<span class="string">`order`</span>, FROM_UNIXTIME(yestime) FROM tfen</span><br><span class="line">WHERE tid IN(<span class="number">7512</span>, <span class="number">7514</span>) </span><br><span class="line">GROUP BY tid </span><br><span class="line">ORDER BY <span class="string">`order`</span> DESC ;</span><br><span class="line">结果不对</span><br><span class="line">SELECT id,tid,<span class="string">`order`</span>,FROM_UNIXTIME(yestime) FROM (</span><br><span class="line">SELECT * FROM tfen WHERE tid IN(<span class="number">7512</span>, <span class="number">7514</span>) ORDER BY <span class="string">`order`</span> DESC </span><br><span class="line">) AS t </span><br><span class="line">GROUP BY tid</span><br><span class="line">除非记录完全相同，否则 mysql 不保证每次 group by 结果相同</span><br></pre></td></tr></table></figure>
<h3 id="mysql索引测试"><a href="#mysql索引测试" class="headerlink" title="mysql索引测试"></a>mysql索引测试</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">命令行直接查询sql</span><br><span class="line">mysql -vv -uroot -h127<span class="number">.0</span><span class="number">.0</span><span class="number">.1</span> -P3306 -p123456 -Dtest -e<span class="string">"select count(*) from test where a = 123467 and b &gt; 123954"</span>;</span><br><span class="line">mysql: [Warning] Using a password on the command line interface can be insecure.</span><br><span class="line">--------------</span><br><span class="line">select count(*) <span class="keyword">from</span> test where a = <span class="number">123467</span> and b &gt; <span class="number">123954</span></span><br><span class="line">--------------</span><br><span class="line"></span><br><span class="line">+----------+</span><br><span class="line">| count(*) |</span><br><span class="line">+----------+</span><br><span class="line">|        <span class="number">0</span> |</span><br><span class="line">+----------+</span><br><span class="line"><span class="number">1</span> row <span class="keyword">in</span> set (<span class="number">4.16</span> sec)</span><br><span class="line">localhost:~ ws$ mysql -vv -uws -p123456 -Dtest -e<span class="string">"select sql_no_cache count(*) from test where a = 26727 and b &gt; 15512"</span></span><br><span class="line">mysql: [Warning] Using a password on the command line interface can be insecure.</span><br><span class="line">--------------</span><br><span class="line">select sql_no_cache count(*) <span class="keyword">from</span> test where a = <span class="number">26727</span> and b &gt; <span class="number">15512</span></span><br><span class="line">--------------</span><br><span class="line"></span><br><span class="line">+----------+</span><br><span class="line">| count(*) |</span><br><span class="line">+----------+</span><br><span class="line">|       <span class="number">31</span> |</span><br><span class="line">+----------+</span><br><span class="line"><span class="number">1</span> row <span class="keyword">in</span> set, <span class="number">1</span> warning (<span class="number">0.32</span> sec)</span><br><span class="line">https:<span class="comment">//learnku.com/laravel/t/33768</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL-避坑宝典"><a href="#MySQL-避坑宝典" class="headerlink" title="MySQL 避坑宝典"></a>MySQL 避坑宝典</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line">修改表的默认字符集不会改表各个字段的字符集   ALTER TABLE tbl_name [DEFAULT] CHARACTER SET <span class="string">'UTF8'</span> 误认为会修改所有字段的字符集，但实际上它只会影响后续新增的字段不会改表已有字段的字符集。如果想修改整张表所有字段的字符集建议使用 ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;</span><br><span class="line"></span><br><span class="line"> 隐式类型转换有无法命中索引的风险，在高并发、大数据量的情况下，命不中索引带来的后果非常严</span><br><span class="line"> SELECT * FROM sakila.film WHERE length &gt;= <span class="string">'60'</span>;</span><br><span class="line"></span><br><span class="line">对于 SELECT COUNT (*) 类型的请求如果不要求精度，建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。</span><br><span class="line"></span><br><span class="line">默认 MySQL 会对 <span class="string">'GROUP BY col1, col2, ...'</span> 请求按如下顺序排序 <span class="string">'ORDER BY col1, col2, ...'</span>。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生，如果不需要排序建议添加 <span class="string">'ORDER BY NULL'</span>。</span><br><span class="line">select c1,c2,c3 <span class="keyword">from</span> t1 where c1=<span class="string">'foo'</span> group by c2</span><br><span class="line">当 GROUP BY 条件为表达式或函数时会使用到临时表，如果在未指定 WHERE 或 WHERE 条件返回的结果集较大时性能会很差。select description <span class="keyword">from</span> film where title =<span class="string">'ACADEMY DINOSAUR'</span> GROUP BY length-language_id;</span><br><span class="line"> 删除全表时建议使用 TRUNCATE 替代 DELETE</span><br><span class="line"> 当表结构发生变更，如果 INSERT 或 REPLACE 请求不明确指定列名，请求的结果将会与预想的不同；建议使用 “INSERT INTO tbl (col1，col2) VALUES ...” 代替。</span><br><span class="line"> 整型定义建议采用 INT (<span class="number">10</span>) 或 BIGINT (<span class="number">20</span>)</span><br><span class="line"> INT (M) 在 integer 数据类型中，M 表示最大显示宽度。 在 INT (M) 中，M 的值跟 INT (M) 所占多少存储空间并无任何关系。 INT (<span class="number">3</span>)、INT (<span class="number">4</span>)、INT (<span class="number">8</span>) 在磁盘上都是占用 <span class="number">4</span> bytes 的存储空间。</span><br><span class="line"> varchar 是可变长字符串，不预先分配存储空间，长度不要超过 <span class="number">255</span>，如果存储长度过长 MySQL 将定义字段类型为 text，独立出来一张表，用主键来对应，避免影响其它字段索引效率。</span><br><span class="line"> COUNT (DISTINCT col) 计算该列除 NULL 之外的不重复行数，注意 COUNT (DISTINCT col, col2) 如果其中一列全为 NULL 那么即使另一列有不同的值，也返回 <span class="number">0</span>。</span><br><span class="line"></span><br><span class="line">MyISAM 表对于 COUNT (*) 统计全表行数进行了特殊的优化，通常情况下非常快。但对于非 MyISAM 表或指定了某些 WHERE 条件，COUNT (*) 操作需要扫描大量的行才能获取精确的结果，性能也因此不佳。有时候某些业务场景并不需要完全精确的 COUNT 值，此时可以用近似值来代替。EXPLAIN 出来的优化器估算的行数就是一个不错的近似值，执行 EXPLAIN 并不需要真正去执行查询，所以成本很低。</span><br><span class="line">不要使用 COUNT (col) 或 COUNT (常量) 来替代 COUNT (*), COUNT (*) 是 SQL92 定义的标准统计行数的方法，跟数据无关，跟 NULL 和非 NULL 也无关。</span><br><span class="line">当某一列的值全是 NULL 时，COUNT (COL) 的返回结果为 <span class="number">0</span>, 但 SUM (COL) 的返回结果为 NULL，因此使用 SUM () 时需注意 NPE 问题。可以使用如下方式来避免 SUM 的 NPE 问题: SELECT IF (ISNULL (SUM (COL)), <span class="number">0</span>, SUM (COL)) FROM tbl</span><br><span class="line"> 触发器的执行没有反馈和日志，隐藏了实际的执行步骤，当数据库出现问题是，不能通过慢日志分析触发器的具体执行情况，不易发现问题。在 MySQL 中，触发器不能临时关闭或打开，在数据迁移或数据恢复等场景下，需要临时 drop 触发器，可能影响到生产环境。</span><br><span class="line">不建议使用存储过程  存储过程无版本控制，配合业务的存储过程升级很难做到业务无感知。存储过程在拓展和移植上也存在问题。</span><br><span class="line">当前 MySQL 版本不支持在子查询中进行 <span class="string">'LIMIT &amp; IN/ALL/ANY/SOME'</span>。</span><br><span class="line">SELECT * FROM staff WHERE name IN (SELECT NAME FROM customer ORDER BY name LIMIT <span class="number">1</span>)</span><br><span class="line"> DISTINCT 关键字在对元组排序后删除重复。相反，考虑使用一个带有 EXISTS 关键字的子查询，您可以避免返回整个表。</span><br><span class="line"> SELECT DISTINCT c.c_id, c.c_name FROM c,e WHERE e.c_id = c.c_id</span><br><span class="line"></span><br><span class="line">DUAL 表为虚拟表，不需要创建即可使用，也不建议服务以 DUAL 命名表。</span><br><span class="line"></span><br><span class="line">MySQL 将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。这可能会在 MySQL <span class="number">5.6</span> 版本中得到改善，但对于 <span class="number">5.1</span> 及更早版本，建议将该类查询分别重写为 JOIN 或 LEFT OUTER JOIN。</span><br><span class="line">建议普通二级索引以 idx_为前缀，唯一索引以 uniq_为前缀。</span><br><span class="line"><span class="string">"&lt;&gt;"</span> 才是标准 SQL 中的不等于运算符 不是！=</span><br><span class="line">数据库必须字段 （<span class="string">`last_update_time`</span> TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT <span class="string">' 最后更新时间 '</span>; <span class="string">`is_del`</span> TINYINT (<span class="number">1</span>) UNSIGNED NOT NULL DEFAULT <span class="string">'0'</span> COMMENT <span class="string">' 是否删除 0：未删除 1：已删除 '</span>）</span><br><span class="line">建议使用 datetime 替换 timestamp 类型，且默认值设置为 <span class="number">1970</span><span class="number">-01</span><span class="number">-01</span> <span class="number">00</span>:<span class="number">00</span>:<span class="number">00</span>。 datetime 类型能保存大范围的值，从 <span class="number">1001</span> 年到 <span class="number">9999</span> 年，且与时区无关。使用 <span class="number">8</span> 个字节的存储空间（比 timestamp 多出 <span class="number">4</span> 字节）</span><br><span class="line">SELECT INTO OUTFILE 需要授予 FILE 权限，这通过会引入安全问题。LOAD DATA 虽然可以提高数据导入速度，但同时也可能导致从库同步延迟过大。</span><br><span class="line">LOAD DATA INFILE <span class="string">'data.txt'</span> INTO TABLE db2.my_table;</span><br><span class="line">UPDATE/DELETE 操作不要指定 ORDER BY 条件。</span><br><span class="line">UPDATE/DELETE 操作使用 LIMIT 条件和不添加 WHERE 条件一样危险，它可将会导致主从数据不一致或从库同步中断。</span><br><span class="line">没有 ORDER BY 的 LIMIT 会导致非确定性的结果，这取决于查询执行计划。</span><br><span class="line">SQL 返回的列既不在聚合函数中也不是 GROUP BY 表达式的列中，因此这些值的结果将是非确定性的。如：select a, b, c <span class="keyword">from</span> tbl where foo=<span class="string">"bar"</span> group by a，该 SQL 返回的结果就是不确定的。</span><br><span class="line">字符串字面上看起来像 IP 地址，但不是 INET_ATON () 的参数，表示数据被存储为字符而不是整数。将 IP 地址存储为整数更为有效。</span><br><span class="line">当主键为自增键时使用 INSERT ON DUPLICATE KEY UPDATE 可能会导致主键出现大量不连续快速增长，导致主键快速溢出无法继续写入。极端情况下还有可能导致主从数据不一致。</span><br><span class="line">因为 SQL_CALC_FOUND_ROWS 不能很好地扩展，所以可能导致性能问题；建议业务使用其他策略来替代 SQL_CALC_FOUND_ROWS 提供的计数功能，比如：分页结果展示等。 select SQL_CALC_FOUND_ROWS col <span class="keyword">from</span> tbl where id&gt;<span class="number">1000</span></span><br><span class="line"></span><br><span class="line">请提前检查添加唯一索引列的数据唯一性，如果数据不唯一在线表结构调整时将有可能自动将重复列删除，这有可能导致数据丢失。</span><br><span class="line">在 MySQL <span class="number">8.0</span> 之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。SELECT * FROM tbl ORDER BY a DESC, b ASC;</span><br><span class="line"> 未指定主键或主键非 bigint，建议将主键设置为 bigint unsigned。 无主键或唯一键，无法在线变更表结构</span><br><span class="line"> 当需要同时删除或更新多张表时建议使用简单语句，一条 SQL 只删除或更新一张表，尽量不要将多张表的操作在同一条语句。</span><br><span class="line"> UPDATE users u LEFT JOIN hobby h ON u.id = h.uid SET u.name = <span class="string">'pianoboy'</span> WHERE h.hobby = <span class="string">'piano'</span>;</span><br><span class="line">将嵌套查询重写为 JOIN 通常会导致更高效的执行和更有效的优化</span><br><span class="line">https:<span class="comment">//github.com/XiaoMi/soar/blob/master/doc/heuristic.md</span></span><br><span class="line">https:<span class="comment">//learnku.com/articles/25270</span></span><br></pre></td></tr></table></figure>
<h3 id="数据中的排名"><a href="#数据中的排名" class="headerlink" title="数据中的排名"></a>数据中的排名</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line">CREATE TABLE IF NOT EXISTS <span class="string">`employee`</span> (</span><br><span class="line">  <span class="string">`id`</span>     INT                  AUTO_INCREMENT PRIMARY KEY,</span><br><span class="line">  <span class="string">`name`</span>   VARCHAR(<span class="number">10</span>) NOT NULL DEFAULT <span class="string">''</span>,</span><br><span class="line">  <span class="string">`income`</span> INT         NOT NULL DEFAULT <span class="string">'0'</span></span><br><span class="line">)</span><br><span class="line">  ENGINE = InnoDB</span><br><span class="line">  DEFAULT CHARSET = utf8;</span><br><span class="line"></span><br><span class="line">INSERT INTO <span class="string">`employee`</span> (<span class="string">`name`</span>, <span class="string">`income`</span>)</span><br><span class="line">VALUES (<span class="string">'麻子'</span>, <span class="number">20000</span>);</span><br><span class="line">INSERT INTO <span class="string">`employee`</span> (<span class="string">`name`</span>, <span class="string">`income`</span>)</span><br><span class="line">VALUES (<span class="string">'李四'</span>, <span class="number">12000</span>);</span><br><span class="line">INSERT INTO <span class="string">`employee`</span> (<span class="string">`name`</span>, <span class="string">`income`</span>)</span><br><span class="line">VALUES (<span class="string">'张三'</span>, <span class="number">10000</span>);</span><br><span class="line">INSERT INTO <span class="string">`employee`</span> (<span class="string">`name`</span>, <span class="string">`income`</span>)</span><br><span class="line">VALUES (<span class="string">'王二'</span>, <span class="number">16000</span>);</span><br><span class="line">INSERT INTO <span class="string">`employee`</span> (<span class="string">`name`</span>, <span class="string">`income`</span>)</span><br><span class="line">VALUES (<span class="string">'土豪'</span>, <span class="number">40000</span>);</span><br><span class="line">SELECT t1.name, t1.income, COUNT(*) AS rank</span><br><span class="line">FROM employee AS t1,</span><br><span class="line">     employee AS t2</span><br><span class="line">WHERE t1.income &lt; t2.income</span><br><span class="line">   OR (t1.income = t2.income AND t1.name &lt;= t2.name)</span><br><span class="line">GROUP BY t1.name, t1.income</span><br><span class="line">ORDER BY rank;</span><br><span class="line"> </span><br><span class="line"></span><br><span class="line">name	income	rank</span><br><span class="line">土豪	<span class="number">40000</span>	<span class="number">1</span></span><br><span class="line">麻子	<span class="number">20000</span>	<span class="number">2</span></span><br><span class="line">王二	<span class="number">16000</span>	<span class="number">3</span></span><br><span class="line">李四	<span class="number">12000</span>	<span class="number">4</span></span><br><span class="line">张三	<span class="number">10000</span>	<span class="number">5</span></span><br><span class="line">找出中位数的排名数字：</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">SELECT (COUNT(*) + <span class="number">1</span>) DIV <span class="number">2</span> <span class="keyword">as</span> rankFROM employee;</span><br><span class="line">从一组数据中获得中位数</span><br><span class="line">SELECT income AS median</span><br><span class="line">FROM (SELECT t1.name, t1.income, COUNT(*) AS rank</span><br><span class="line">      FROM employee AS t1,</span><br><span class="line">           employee AS t2</span><br><span class="line">      WHERE t1.income &lt; t2.income</span><br><span class="line">         OR (t1.income = t2.income AND t1.name &lt;= t2.name)</span><br><span class="line">      GROUP BY t1.name, t1.income</span><br><span class="line">      ORDER BY rank) t3</span><br><span class="line">WHERE rank = (SELECT (COUNT(*) + <span class="number">1</span>) DIV <span class="number">2</span> FROM employee)</span><br><span class="line">索引的类型，从好到坏的情况是：system&gt;<span class="keyword">const</span>&gt;range&gt;index&gt;All</span><br><span class="line">https:<span class="comment">//learnku.com/articles/18390</span></span><br></pre></td></tr></table></figure>
<h3 id="树查询"><a href="#树查询" class="headerlink" title="树查询"></a>树查询</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line">CREATE TABLE category(</span><br><span class="line">        category_id INT AUTO_INCREMENT PRIMARY KEY,</span><br><span class="line">        name VARCHAR(<span class="number">20</span>) NOT NULL,</span><br><span class="line">        parent INT DEFAULT NULL</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">INSERT INTO category VALUES(<span class="number">1</span>,<span class="string">'ELECTRONICS'</span>,NULL),(<span class="number">2</span>,<span class="string">'TELEVISIONS'</span>,<span class="number">1</span>),(<span class="number">3</span>,<span class="string">'TUBE'</span>,<span class="number">2</span>),</span><br><span class="line">        (<span class="number">4</span>,<span class="string">'LCD'</span>,<span class="number">2</span>),(<span class="number">5</span>,<span class="string">'PLASMA'</span>,<span class="number">2</span>),(<span class="number">6</span>,<span class="string">'PORTABLE ELECTRONICS'</span>,<span class="number">1</span>),(<span class="number">7</span>,<span class="string">'MP3 PLAYERS'</span>,<span class="number">6</span>),(<span class="number">8</span>,<span class="string">'FLASH'</span>,<span class="number">7</span>),</span><br><span class="line">        (<span class="number">9</span>,<span class="string">'CD PLAYERS'</span>,<span class="number">6</span>),(<span class="number">10</span>,<span class="string">'2 WAY RADIOS'</span>,<span class="number">6</span>);</span><br><span class="line"></span><br><span class="line">SELECT * FROM category ORDER BY category_id;</span><br><span class="line">+-------------+----------------------+--------+</span><br><span class="line">| category_id | name                 | parent |</span><br><span class="line">+-------------+----------------------+--------+</span><br><span class="line">|           <span class="number">1</span> | ELECTRONICS          |   NULL |</span><br><span class="line">|           <span class="number">2</span> | TELEVISIONS          |      <span class="number">1</span> |</span><br><span class="line">|           <span class="number">3</span> | TUBE                 |      <span class="number">2</span> |</span><br><span class="line">|           <span class="number">4</span> | LCD                  |      <span class="number">2</span> |</span><br><span class="line">|           <span class="number">5</span> | PLASMA               |      <span class="number">2</span> |</span><br><span class="line">|           <span class="number">6</span> | PORTABLE ELECTRONICS |      <span class="number">1</span> |</span><br><span class="line">|           <span class="number">7</span> | MP3 PLAYERS          |      <span class="number">6</span> |</span><br><span class="line">|           <span class="number">8</span> | FLASH                |      <span class="number">7</span> |</span><br><span class="line">|           <span class="number">9</span> | CD PLAYERS           |      <span class="number">6</span> |</span><br><span class="line">|          <span class="number">10</span> | <span class="number">2</span> WAY RADIOS         |      <span class="number">6</span> |</span><br><span class="line">+-------------+----------------------+--------+</span><br><span class="line">SELECT t1.name AS lev1, t2.name <span class="keyword">as</span> lev2, t3.name <span class="keyword">as</span> lev3, t4.name <span class="keyword">as</span> lev4</span><br><span class="line">FROM category AS t1</span><br><span class="line">LEFT JOIN category AS t2 ON t2.parent = t1.category_id</span><br><span class="line">LEFT JOIN category AS t3 ON t3.parent = t2.category_id</span><br><span class="line">LEFT JOIN category AS t4 ON t4.parent = t3.category_id</span><br><span class="line">WHERE t1.name = <span class="string">'ELECTRONICS'</span>;</span><br><span class="line"></span><br><span class="line">+-------------+----------------------+--------------+-------+</span><br><span class="line">| lev1        | lev2                 | lev3         | lev4  |</span><br><span class="line">+-------------+----------------------+--------------+-------+</span><br><span class="line">| ELECTRONICS | TELEVISIONS          | TUBE         | NULL  |</span><br><span class="line">| ELECTRONICS | TELEVISIONS          | LCD          | NULL  |</span><br><span class="line">| ELECTRONICS | TELEVISIONS          | PLASMA       | NULL  |</span><br><span class="line">| ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS  | FLASH |</span><br><span class="line">| ELECTRONICS | PORTABLE ELECTRONICS | CD PLAYERS   | NULL  |</span><br><span class="line">| ELECTRONICS | PORTABLE ELECTRONICS | <span class="number">2</span> WAY RADIOS | NULL  |</span><br><span class="line">+-------------+----------------------+--------------+-------+</span><br><span class="line">SELECT t1.name FROM</span><br><span class="line">category AS t1 LEFT JOIN category <span class="keyword">as</span> t2</span><br><span class="line">ON t1.category_id = t2.parent</span><br><span class="line">WHERE t2.category_id IS NULL;</span><br><span class="line"></span><br><span class="line">+--------------+</span><br><span class="line">| name         |</span><br><span class="line">+--------------+</span><br><span class="line">| TUBE         |</span><br><span class="line">| LCD          |</span><br><span class="line">| PLASMA       |</span><br><span class="line">| FLASH        |</span><br><span class="line">| CD PLAYERS   |</span><br><span class="line">| <span class="number">2</span> WAY RADIOS |</span><br><span class="line">+--------------+</span><br><span class="line">http:<span class="comment">//mikehillyer.com/articles/managing-hierarchical-data-in-mysql/</span></span><br><span class="line">https:<span class="comment">//learnku.com/articles/33688</span></span><br></pre></td></tr></table></figure>
<h3 id="profile-工具"><a href="#profile-工具" class="headerlink" title="profile 工具"></a>profile 工具</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//开启操作</span></span><br><span class="line">mysql&gt; set profiling = on;</span><br><span class="line">Query OK, <span class="number">0</span> rows affected, <span class="number">1</span> warning (<span class="number">0.00</span> sec)</span><br><span class="line"></span><br><span class="line"><span class="comment">//查看是否开启成功</span></span><br><span class="line">mysql&gt; show variables like <span class="string">'%profil%'</span>;</span><br><span class="line">+------------------------+-------+</span><br><span class="line">| Variable_name          | Value |</span><br><span class="line">+------------------------+-------+</span><br><span class="line">| have_profiling         | YES   |</span><br><span class="line">| profiling              | ON    |<span class="comment">//开启成功</span></span><br><span class="line">| profiling_history_size | <span class="number">15</span>    |</span><br><span class="line">mysql&gt; select * <span class="keyword">from</span> article where no_index=<span class="number">666666</span>;</span><br><span class="line">mysql&gt; show profiles;</span><br><span class="line">+----------+------------+---------------------------------------------+</span><br><span class="line">| Query_ID | Duration   | Query                                       |</span><br><span class="line">+----------+------------+---------------------------------------------+</span><br><span class="line">|        <span class="number">1</span> | <span class="number">0.00150700</span> | show variables like <span class="string">'%profil%'</span>              |</span><br><span class="line">|        <span class="number">2</span> | <span class="number">0.01481100</span> | select * <span class="keyword">from</span> article where no_index=<span class="number">666666</span> |</span><br><span class="line">+----------+------------+---------------------------------------------+</span><br><span class="line"><span class="number">2</span> rows <span class="keyword">in</span> set, <span class="number">1</span> warning (<span class="number">0.00</span> sec)</span><br><span class="line"></span><br><span class="line">mysql&gt; show profile <span class="keyword">for</span> query <span class="number">2</span>;</span><br><span class="line">+----------------------+----------+</span><br><span class="line">| Status               | Duration |</span><br><span class="line">+----------------------+----------+</span><br><span class="line">| starting             | <span class="number">0.000291</span> |</span><br><span class="line">| checking permissions | <span class="number">0.000007</span> |</span><br></pre></td></tr></table></figure>
<h3 id="limit-语句的索引使用优化"><a href="#limit-语句的索引使用优化" class="headerlink" title="limit 语句的索引使用优化"></a>limit 语句的索引使用优化</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">针对于 limit 语句的优化，我们可以在它前面加 order by 索引字段</span><br><span class="line"></span><br><span class="line">如果 order by 的字段是索引，会先去索引文件中查找指定行数的数据</span><br><span class="line">mysql&gt; explain select sql_no_cache  * <span class="keyword">from</span> article order by id  limit <span class="number">90000</span>,<span class="number">10</span> \G;</span><br><span class="line">索引覆盖 + 延时关联</span><br><span class="line"></span><br><span class="line">原理：主要利用索引覆盖查询，把覆盖索引查询返回的 id 作为与我们要查询记录的 id 进行相关联，</span><br><span class="line"></span><br><span class="line">mysql&gt; select sql_no_cache  * <span class="keyword">from</span> article limit <span class="number">1000000</span>,<span class="number">10</span>;</span><br><span class="line">mysql&gt; select t1.* <span class="keyword">from</span> article <span class="keyword">as</span> t1 inner join (select id <span class="keyword">as</span> pid <span class="keyword">from</span> article  limit <span class="number">10000</span>,<span class="number">10</span>) <span class="keyword">as</span> t2 on t1.id=t2.pid;</span><br><span class="line">https:<span class="comment">//learnku.com/articles/28609#replies</span></span><br></pre></td></tr></table></figure>
<h3 id="group-by-城市行业后获取工资最低"><a href="#group-by-城市行业后获取工资最低" class="headerlink" title="group by 城市行业后获取工资最低"></a>group by 城市行业后获取工资最低</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">MySQL 求助， group by 城市行业后获取工资最低的一条数据https:<span class="comment">//cn.v2ex.com/t/600001#reply34</span></span><br><span class="line">select business.id, business.money <span class="keyword">from</span> business join (select city, min(money) <span class="keyword">as</span> min_money <span class="keyword">from</span> business group by city) <span class="keyword">as</span> temp on business.city = temp.city and business.money = temp.min_money;</span><br><span class="line"></span><br><span class="line">select * <span class="keyword">from</span> (select * <span class="keyword">from</span> T order by money limit <span class="number">100</span>) tmp group by city, business;</span><br></pre></td></tr></table></figure>
<h3 id="每个司机今天最早的一笔订单"><a href="#每个司机今天最早的一笔订单" class="headerlink" title="每个司机今天最早的一笔订单"></a>每个司机今天最早的一笔订单</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">https:<span class="comment">//mp.weixin.qq.com/s?__biz=MzI1MzY0MzE4Mg==&amp;mid=2247483773&amp;idx=1&amp;sn=d2578386819d66147f09209ecc834436&amp;chksm=e9d011bcdea798aa21d65f935567eb1c66511d2fc9925b51ccea6a4985a21d85d95c01a513b3&amp;scene=21#wechat_redirect</span></span><br><span class="line"></span><br><span class="line">select name,sex,register,ordertime <span class="keyword">from</span> userinfo,orderinfo where userinfo.id = orderinfo.userid group by orderinfo.userid order by orderinfo.ordertime limit <span class="number">1</span></span><br><span class="line">select name,sex,register,min(ordertime) <span class="keyword">from</span> userinfo,orderinfo where userinfo.id = orderinfo.userid group by orderinfo.userid</span><br><span class="line">张三的第一个用户应该是二号，细心的你可能已经发现问题了，还是group by的问题，它返回的是链接之后分组的第一条记录，min(ordertime)相当于是不在表中的一个新加入的字段，它的值通过min函数计算而来，所以会出现上面的结果</span><br><span class="line"></span><br><span class="line">select name,sex,register,ordertime,orderuser <span class="keyword">from</span> userinfo left outer join orderinfo on userinfo.id = orderinfo.userid where orderinfo.ordertime <span class="keyword">in</span> (select min(ordertime) <span class="keyword">from</span> orderinfo group by userid)</span><br><span class="line">where子句限定了ordertime的取值范围，所以不会出现那些没有订单信息的用户，所以我们还要对语句作如下修改，让ordertime可以为Null值：</span><br><span class="line">select name,sex,register,ordertime,orderuser <span class="keyword">from</span> userinfo left outer join orderinfo on userinfo.id = orderinfo.userid where orderinfo.ordertime <span class="keyword">in</span> (select min(ordertime) <span class="keyword">from</span> orderinfo group by userid) or orderinfo.ordertime is Null</span><br><span class="line"></span><br><span class="line">select name,sex,register,ordertime,orderuser <span class="keyword">from</span> userinfo,orderinfo,(select userid,min(ordertime) <span class="keyword">as</span> ordertime2 <span class="keyword">from</span> orderinfo group by userid) <span class="keyword">as</span> orderinfo2 where userinfo.id = orderinfo.userid and orderinfo.ordertime = orderinfo2.ordertime2 and orderinfo.userid = orderinfo2.userid</span><br><span class="line"></span><br><span class="line">mysql没有row_number()/rank()/dense_rank() over(partition by)这样高级的sql语法，不过我们可以通过编程的方式来模拟实现类似的功能</span><br><span class="line">select u.name,u.sex,u.register,o.ordertime,o.orderuser <span class="keyword">from</span> userinfo <span class="keyword">as</span> u,(select orderinfo.*,<span class="keyword">if</span>(@userid = orderinfo.userid,@rank:=@rank+<span class="number">1</span>,@rank:=<span class="number">1</span>) <span class="keyword">as</span> rank,@userid:=orderinfo.userid <span class="keyword">from</span> orderinfo,(select @rank:=<span class="number">0</span>,@userid:=NULL) <span class="keyword">as</span> b order by orderinfo.userid,orderinfo.ordertime) <span class="keyword">as</span> o where u.id = o.userid and o.rank = <span class="number">1</span></span><br><span class="line"></span><br><span class="line">mysql中变量不用事前申明，在用的时候直接用“@变量名”使用就可以了。</span><br><span class="line">第一种用法：set @num=<span class="number">1</span>; 或set @num:=<span class="number">1</span>; <span class="comment">//这里要使用变量来保存数据，直接使用@num变量</span></span><br><span class="line">第二种用法：select @num:=<span class="number">1</span>; 或 select @num:=字段名 <span class="keyword">from</span> 表名 where ……</span><br><span class="line">注意上面两种赋值符号，使用set时可以用“=”或“：=”，但是使用select时必须用“：=赋值”</span><br><span class="line"></span><br><span class="line">使用变量添加行号</span><br><span class="line"></span><br><span class="line">我们可以设置一个初始行号，接下来在 select语句中不断改变行号的值即可：</span><br><span class="line"></span><br><span class="line">set @i = <span class="number">0</span>;</span><br><span class="line">select   (@i:=@i+<span class="number">1</span>)  <span class="keyword">as</span>   i,userinfo.*   <span class="keyword">from</span>   userinfo</span><br><span class="line">如果使用一句话，我们可以将设置初始值的过程放在<span class="keyword">from</span>后面：</span><br><span class="line"></span><br><span class="line">select   (@i:=@i+<span class="number">1</span>)  <span class="keyword">as</span>   i,userinfo.*   <span class="keyword">from</span>   userinfo,(select   @i:=<span class="number">0</span>)   <span class="keyword">as</span>  it </span><br><span class="line"></span><br><span class="line">我们根据司机的注册时间划分司机类型：</span><br><span class="line"></span><br><span class="line">select name,<span class="keyword">if</span>(register &gt; <span class="string">'2017-08-05'</span>,<span class="string">'A'</span>,<span class="string">'B'</span>) <span class="keyword">as</span> type <span class="keyword">from</span> userinfo</span><br><span class="line">select orderinfo.*,<span class="keyword">if</span>(@userid = orderinfo.userid,@rank:=@rank+<span class="number">1</span>,@rank:=<span class="number">1</span>) <span class="keyword">as</span> rank,@userid:=orderinfo.userid <span class="keyword">from</span> orderinfo,(select @rank:=<span class="number">0</span>,@userid:=NULL) <span class="keyword">as</span> b</span><br></pre></td></tr></table></figure>
<h3 id="删除重复"><a href="#删除重复" class="headerlink" title="删除重复"></a>删除重复</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">select *<span class="keyword">from</span> hso_minline where phymin <span class="keyword">in</span>(select phymin <span class="keyword">from</span> hso_minline where symbol=<span class="string">'xau'</span> and uts&gt;<span class="number">1565971200</span> group by phymin having count(*) &gt;<span class="number">1</span>) and  symbol=<span class="string">'xau'</span> and uts&gt;<span class="number">1565971200</span> limit <span class="number">20</span>;</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"><span class="keyword">delete</span> <span class="keyword">from</span> hso_minline WHERE id not IN (SELECT bid FROM (SELECT min(id) <span class="keyword">as</span> bid FROM hso_minline where symbol=<span class="string">'xau'</span> and uts&gt;<span class="number">1565971200</span>  GROUP BY phymin)<span class="keyword">as</span> b) and symbol=<span class="string">'xau'</span> and uts&gt;<span class="number">1565971200</span>;</span><br></pre></td></tr></table></figure>
<h3 id="MySQL-通过-binlog-恢复数据"><a href="#MySQL-通过-binlog-恢复数据" class="headerlink" title="MySQL 通过 binlog 恢复数据"></a>MySQL 通过 binlog 恢复数据</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line">如果不知道 mysql 的配置文件路径，可以使用 mysql 命令进行查找，</span><br><span class="line"></span><br><span class="line">mysql --verbose --help|grep -A <span class="number">1</span> <span class="string">'Default options’ #该命令会罗列出my.cnf顺序查找的路径。</span></span><br><span class="line"><span class="string">Default options are read from the following files in the given order:</span></span><br><span class="line"><span class="string">/etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf</span></span><br><span class="line"><span class="string">binlog 就是 binary log，二进制日志文件，记录所有数据库更新语句，包括表更新和记录更新，即数据操纵语言 (DML)，binlog 主要用于数据恢复和配置主从复制等；</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">数据恢复：当数据库误删或者发生不可描述的事情时，可以通过 binlog 恢复到某个时间点的数据。</span></span><br><span class="line"><span class="string">主从复制：当有数据库更新之后，主库通过 binlog 记录并通知从库进行更新，从而保证主从数据库数据一致；</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">log_bin=ON</span></span><br><span class="line"><span class="string">log_bin_basename=/path/bin-log</span></span><br><span class="line"><span class="string">log_bin_index=/path/bin-log.index</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">statement 格式日志，执行 mysqlbinlog /path/bin-log.000001，可以直接看到原始执行的 SQL 语句</span></span><br><span class="line"><span class="string">row 格式日志，则可读性没有那么好，但仍可通过参数使文档更加可读 mysqlbinlog -v /path/bin-log.000001</span></span><br><span class="line"><span class="string">mysqlbinlog 两对非常重要的参数</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">--start-datetime --stop-datetime 解析某一个时间段内的 binlog；</span></span><br><span class="line"><span class="string">--start-position --stop-position 解析在两个 position 之间的 binlog；</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">CREATE TABLE `users` (</span></span><br><span class="line"><span class="string">          `id` int(11) unsigned NOT NULL AUTO_INCREMENT,</span></span><br><span class="line"><span class="string">          `name` varchar(255) DEFAULT NULL,</span></span><br><span class="line"><span class="string">          `age` int(8) DEFAULT NULL,</span></span><br><span class="line"><span class="string">          PRIMARY KEY (`id`)</span></span><br><span class="line"><span class="string"> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;</span></span><br><span class="line"><span class="string"> INSERT INTO `users` (`id`, `name`, `age`)</span></span><br><span class="line"><span class="string">    VALUES</span></span><br><span class="line"><span class="string">        (null, '</span>姓名一<span class="string">', 5);</span></span><br><span class="line"><span class="string"> </span></span><br><span class="line"><span class="string"> mysqldump -uroot -p T &gt; /path/xxx.sql;   # 备份数据库</span></span><br><span class="line"><span class="string"> show master status;   # 查看当前的position位置，此时值为154</span></span><br><span class="line"><span class="string">INSERT INTO `users` (`id`, `name`, `age`)</span></span><br><span class="line"><span class="string">VALUES</span></span><br><span class="line"><span class="string"> (null, '</span>姓名二<span class="string">', 13),</span></span><br><span class="line"><span class="string"> (null, '</span>姓名三<span class="string">', 14),</span></span><br><span class="line"><span class="string"> (null, '</span>姓名四<span class="string">', 15),</span></span><br><span class="line"><span class="string"> (null, '</span>姓名五<span class="string">', 16),</span></span><br><span class="line"><span class="string"> (null, '</span>姓名六<span class="string">', 17);</span></span><br><span class="line"><span class="string"> </span></span><br><span class="line"><span class="string"> update users set age = 5；</span></span><br><span class="line"><span class="string"> INSERT INTO `users` (`id`, `name`, `age`)</span></span><br><span class="line"><span class="string"> VALUES</span></span><br><span class="line"><span class="string"> (null, '</span>姓名七<span class="string">', 16),</span></span><br><span class="line"><span class="string"> (null, '</span>姓名八<span class="string">', 18);</span></span><br><span class="line"><span class="string"> mysqlbinlog --start-position=154  --stop-position=513  bin-log.000001 &gt; /path/bak.sql;</span></span><br><span class="line"><span class="string"> mysql -uroot -p &lt; /path/bak.sql;</span></span><br><span class="line"><span class="string"> </span></span><br><span class="line"><span class="string"> https://learnku.com/articles/20628</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL-8-0-加密方式不兼容"><a href="#MySQL-8-0-加密方式不兼容" class="headerlink" title="MySQL 8.0 加密方式不兼容"></a>MySQL 8.0 加密方式不兼容</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">Illuminate\Database\QueryException  : SQLSTATE[HY000] [<span class="number">2054</span>] The server requested authentication method unknown to the client (SQL: select * <span class="keyword">from</span> information_schema.tables where table_schema = weibo and table_name = migrations and table_type = <span class="string">'BASE TABLE'</span>)</span><br><span class="line">运行 php artisan migrate -v 查看更详细信息如下：</span><br><span class="line"></span><br><span class="line"> Exception trace:</span><br><span class="line"></span><br><span class="line">  <span class="number">1</span>   PDOException::(<span class="string">"PDO::__construct(): The server requested authentication method unknown to the client [caching_sha2_password]"</span>)</span><br><span class="line">      /www/weibo/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:<span class="number">70</span></span><br><span class="line">      MySQL <span class="number">8.0</span> 使用了新的密码加密方式：caching_sha2_password，而许多客户端还不支持这种方式，比如 php 的 PDO 扩展。</span><br><span class="line">      </span><br><span class="line">     修改 docker-compose.yml 的 mysql 服务部分，添加一行：</span><br><span class="line">     </span><br><span class="line">      command: --<span class="keyword">default</span>-authentication-plugin=mysql_native_password</span><br><span class="line">     my.cnf 配置文件中 [mysqld] 下添加一行：</span><br><span class="line">     <span class="keyword">default</span>-authentication-plugin=mysql_native_password</span><br><span class="line">     重新构建服务，依次执行：docker-compose down, docker-compose up -d</span><br><span class="line">     运行 docker container exec -it &lt;container_name or id&gt; <span class="regexp">/bin/</span>bash 进入 mysql 所在的容器。登录 root 账号：mysql -u root -p &lt;password&gt;，登入 mysql 后依次运行：</span><br><span class="line">     ALTER USER <span class="string">'root'</span>@<span class="string">'localhost'</span> IDENTIFIED WITH mysql_native_password BY <span class="string">'your_password'</span>;</span><br><span class="line">     FLUSH PRIVILEGES; </span><br><span class="line">https:<span class="comment">//learnku.com/articles/34823</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL-安装常见错误"><a href="#MySQL-安装常见错误" class="headerlink" title="MySQL 安装常见错误"></a>MySQL 安装常见错误</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">rpm -Uvh mysql57-community-release-el7<span class="number">-10.</span>noarch.rpm</span><br><span class="line">#命令行出现 mysql57-community-release-el7-8.noarch</span><br><span class="line">rpm -e --nodeps mysql57-community-release-el7<span class="number">-8.</span>noarch</span><br><span class="line"><span class="number">2.</span> 依赖报错</span><br><span class="line"></span><br><span class="line"><span class="built_in">Error</span>: Package: mysql-community-server<span class="number">-5.7</span><span class="number">.20</span><span class="number">-1.</span>el7.x86_64 (mysql57-community)</span><br><span class="line">           Requires: libsasl2.so<span class="number">.3</span>()(<span class="number">64</span>bit)</span><br><span class="line"><span class="built_in">Error</span>: Package: mysql-community-client<span class="number">-5.7</span><span class="number">.20</span><span class="number">-1.</span>el7.x86_64 (mysql57-community)</span><br><span class="line">           Requires: libstdc++.so<span class="number">.6</span>(GLIBCXX_3<span class="number">.4</span><span class="number">.15</span>)(<span class="number">64</span>bit)</span><br><span class="line"><span class="built_in">Error</span>: Package: mysql-community-libs<span class="number">-5.7</span><span class="number">.20</span><span class="number">-1.</span>el7.x86_64 (mysql57-community)</span><br><span class="line">...</span><br><span class="line">分析</span><br><span class="line"></span><br><span class="line">因为 旧版本 mysql 的依赖问题；最快的解决方案就是卸载重装</span><br><span class="line"></span><br><span class="line"><span class="number">3.</span> 卸载</span><br><span class="line"></span><br><span class="line"><span class="number">1.</span> 快速删除</span><br><span class="line"></span><br><span class="line">yum remove  mysql mysql-server mysql-libs mysql-server</span><br><span class="line"><span class="number">2.</span> 查找残留文件</span><br><span class="line"></span><br><span class="line">rpm -qa | grep -i mysql</span><br><span class="line">## 将查询出来的文件删除</span><br><span class="line">yum remove mysql-community-common<span class="number">-5.7</span><span class="number">.20</span><span class="number">-1.</span>el6.x86_64</span><br><span class="line">## 删除残余目录</span><br><span class="line">whereis mysql</span><br><span class="line">rm –rf /usr/lib64/mysql</span><br><span class="line"><span class="number">3.</span> 删除依赖</span><br><span class="line"></span><br><span class="line">## 查找依赖 </span><br><span class="line">yum list installed | grep mysql</span><br><span class="line">## 删除找到的依赖</span><br><span class="line">yum -y remove mysql-libs.x86_64</span><br><span class="line"><span class="number">4.</span> 安装新 mysql</span><br><span class="line"></span><br><span class="line"><span class="number">1.</span> 添加镜像源，从官网 downloads 选取</span><br><span class="line"></span><br><span class="line">wget dev.mysql.com/get/mysql-community-release-el6<span class="number">-5.</span>noarch.rpm</span><br><span class="line">yum localinstall mysql-community-release-el6<span class="number">-5.</span>noarch.rpm</span><br><span class="line">yum repolist all | grep mysql</span><br><span class="line">yum-config-manager --disable mysql55-community</span><br><span class="line">yum-config-manager --disable mysql56-community</span><br><span class="line">yum-config-manager --enable mysql57-community-dmr</span><br><span class="line">yum repolist enabled | grep mysql</span><br><span class="line"><span class="number">2.</span> 安装</span><br><span class="line"></span><br><span class="line">yum install mysql-community-server</span><br><span class="line">https:<span class="comment">//learnku.com/articles/35042</span></span><br></pre></td></tr></table></figure>
<h3 id="数据库脏读"><a href="#数据库脏读" class="headerlink" title="数据库脏读"></a>数据库脏读</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">MYSQL查看数据库事务隔离级别</span><br><span class="line"></span><br><span class="line"><span class="number">1</span></span><br><span class="line">show variables like <span class="string">'%isolation%'</span>;</span><br><span class="line">修改MYSQL数据库事务隔离级别</span><br><span class="line"></span><br><span class="line">设置innodb的事务级别方法是：set 作用域 transaction isolation level 事务隔离级别，例如：</span><br><span class="line">SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL &#123;READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE&#125;</span><br><span class="line"> </span><br><span class="line">mysql&gt; set global transaction isolation level read committed; #全局的</span><br><span class="line"></span><br><span class="line">mysql&gt; set session transaction isolation level read committed; #当前会话</span><br><span class="line">http:<span class="comment">//blog.qicunshang.com/2018/02/07/database-dirty-read/</span></span><br></pre></td></tr></table></figure>
<h3 id="创建外键报错"><a href="#创建外键报错" class="headerlink" title="创建外键报错"></a>创建外键报错</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">外键关联的数据结构不对，查看了表的数据结构发现 ID 主键自增是 int unsigned 类型的，而我关联的 parent_id 是 int 类型的，所以数据结构不一致才会报错</span><br><span class="line">Schema:：create（<span class="string">"store_menus'，function（Blueprint $table）&#123;</span></span><br><span class="line"><span class="string">$table-&gt;increments（'id）：</span></span><br><span class="line"><span class="string">$table-&gt;string（'title'）-&gt;upinue（）-&gt;comment（菜单名称）；</span></span><br><span class="line"><span class="string">$table-&gt;integer（'parent_id'）-&gt;index（）-&gt;default（0）-&gt;comment“父类ID’）；</span></span><br><span class="line"><span class="string">https://learnku.com/articles/35353</span></span><br></pre></td></tr></table></figure>
<h3 id="并发测试"><a href="#并发测试" class="headerlink" title="并发测试"></a>并发测试</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">    DB::table(<span class="string">'articles'</span>)-&gt;where(<span class="string">'id'</span> , $request-&gt;id)-&gt;increment(<span class="string">'like'</span>);</span><br><span class="line"><span class="number">100</span>并发结果为<span class="number">100</span></span><br><span class="line">  <span class="keyword">return</span> DB::transaction(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) <span class="title">use</span> (<span class="params">$request</span>)</span>&#123;</span><br><span class="line">       $article = Article::find($request-&gt;id);</span><br><span class="line">       $article-&gt;like += <span class="number">1</span>;</span><br><span class="line">       $article-&gt;save();</span><br><span class="line">       <span class="keyword">return</span> $<span class="keyword">this</span>-&gt;message(<span class="string">'点赞成功！'</span>);</span><br><span class="line">    &#125;);</span><br><span class="line"><span class="number">100</span>并发结果为<span class="number">177</span></span><br><span class="line">.increment 方法编译后的结果就是 update like = like +<span class="number">1</span> where id = <span class="string">'id'</span>,update 语句是行级锁，所有是顺序执行更新的。</span><br><span class="line"><span class="number">2.</span> 在事务里面进行查询之后再更新，MySQL 默认使用 RR 级别隔离，所有可能存在并发请求的时候读取的值是同一个，</span><br><span class="line">这里避免的方式是加上 Article::lockForUpdate ()-&gt;find ($request-&gt;id); 排它锁，目的是在本次事物执行查询的时候，其他事务是不允许读取的，这样才能防止并发下产生的问题。https:<span class="comment">//learnku.com/articles/35337</span></span><br><span class="line">单个请求是可以实现的 只有在多数并发访问的时候才会出现异常</span><br></pre></td></tr></table></figure>
<h3 id="mysql-update超卖"><a href="#mysql-update超卖" class="headerlink" title="mysql update超卖"></a>mysql update超卖</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line">以抢购 <span class="number">100</span> 件商品为例，商品表 num=<span class="number">100</span></span><br><span class="line">在函数 doPageGoodsOrder 中，如果使用如下 sql</span><br><span class="line"></span><br><span class="line">$sql=<span class="string">"update ims_hotmallstore_goods set num=$number where num&gt;0 and id="</span>.$goods[<span class="string">'id'</span>];</span><br><span class="line"></span><br><span class="line">即直接更新数据，不在 sql 中运算，在使用 apache ab 测试时</span><br><span class="line"></span><br><span class="line">ab -n <span class="number">1000</span> -c <span class="number">100</span> http:<span class="comment">//redis.test/demo/test.php?i=2</span></span><br><span class="line"></span><br><span class="line">发现：</span><br><span class="line"></span><br><span class="line">商品表，num 字段不为 <span class="number">0</span></span><br><span class="line">订单表，生成 <span class="number">456</span> 份订单</span><br><span class="line">日志表，<span class="number">1000</span> 条日志，其中抢购成功的即 status=<span class="number">1</span> 的是 <span class="number">100</span> 条</span><br><span class="line">如果在 sql 中计算，即：</span><br><span class="line"></span><br><span class="line">$sql=<span class="string">"update ims_hotmallstore_goods set num=num-"</span>.$goods_number.<span class="string">" where num&gt;0 and id="</span>.$goods[<span class="string">'id'</span>];</span><br><span class="line"></span><br><span class="line">结果正常，num=<span class="number">0</span>，订单 <span class="number">100</span> 条，日志 <span class="number">1000</span> 条</span><br><span class="line">并发高的情况下，必须要用 mysql 的更新锁。</span><br><span class="line">问题出在上面判断库存的时候：</span><br><span class="line"></span><br><span class="line">假设 A 取到的是剩余 <span class="number">100</span> 库存，并发时 B 取到的也是 <span class="number">100</span> 库存</span><br><span class="line">当 A 自行减法算出库存为 <span class="number">99</span> 并更新，这时 C 拿到的库存可能是 <span class="number">100</span>，也可能是 <span class="number">99</span></span><br><span class="line">当 C 自行减一后，算出 <span class="number">98</span> 时，这时候可能 B 算出来是 <span class="number">99</span> 并更新到库存</span><br><span class="line">当 D 获得库存时，可能是 <span class="number">99</span> 还可能是 <span class="number">100</span></span><br><span class="line">以上就会出现这种情况。</span><br><span class="line">解决方案：</span><br><span class="line">使用 mysql 事务处理，在获取库存之前开始处理事务并锁定表，然后结束事务，laravel 文档中有这一条代码</span><br><span class="line"></span><br><span class="line">DB::table(<span class="string">'users'</span>)-&gt;where(<span class="string">'votes'</span>, <span class="string">'&gt;'</span>, <span class="number">100</span>)-&gt;lockForUpdate()-&gt;get();</span><br><span class="line"><span class="comment">// 抢购下单</span></span><br><span class="line">public <span class="function"><span class="keyword">function</span> <span class="title">doPageGoodsStore</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">        $pdo = self::Pdo();</span><br><span class="line">        $goods_id=<span class="number">1</span>;</span><br><span class="line">        <span class="comment">/**诺，问题所在</span></span><br><span class="line"><span class="comment">            对于 redis 来说，它属于单线程的原子性操作，但是 mysql 不是。</span></span><br><span class="line"><span class="comment">            所以这里拿商品数据，你是通过查询数据库获取的。</span></span><br><span class="line"><span class="comment">            而又因为你算库存的时候，通过查询数据库获取到的库存来计算，</span></span><br><span class="line"><span class="comment">            在并发情况下自然会引起不正确，这里的库存数，建议也通过 redis 中存储的热数据来计算</span></span><br><span class="line"><span class="comment">            比如 $stock = $redis-&gt;llen('num');</span></span><br><span class="line"><span class="comment">        **/</span></span><br><span class="line">        $sql=<span class="string">"select id, num, money from ims_hotmallstore_goods where id="</span>.$goods_id;</span><br><span class="line">&#125;</span><br><span class="line">补充第二个问题，看下来是不会的，但是会出现数据的错误，最直接的就是你能看到的超库存。</span><br><span class="line"></span><br><span class="line">当然，这个还有一些隐藏的问题。因为并发，数据库压力比较大，如果实时去 update 和 insert 的话，会出现一些单点故障，比如数据库奔溃。</span><br><span class="line"></span><br><span class="line">我一般入库的做法是在热度过后再批量入库。</span><br><span class="line">https:<span class="comment">//learnku.com/laravel/t/34293</span></span><br></pre></td></tr></table></figure>
<h3 id="mysql5-7-datetime-默认值为‘0000-00-00-00-00-00’值无法创建"><a href="#mysql5-7-datetime-默认值为‘0000-00-00-00-00-00’值无法创建" class="headerlink" title="mysql5.7 datetime 默认值为‘0000-00-00 00:00:00’值无法创建"></a>mysql5.7 datetime 默认值为‘0000-00-00 00:00:00’值无法创建</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span>、使用root登陆数据库 命令界面执行</span><br><span class="line">select @@sql_mode;</span><br><span class="line"> 结果中包含下面两个</span><br><span class="line">NO_ZERO_IN_DATE,NO_ZERO_DATE</span><br><span class="line"><span class="number">2</span>、修改/etc/my.cnf，查找sql_model如果找不到则添加如下代码 </span><br><span class="line">sql_mode=<span class="string">"ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"</span></span><br><span class="line"><span class="number">3</span>、重启mysql</span><br><span class="line">/etc/ini.d/mysql restart</span><br><span class="line">简单几步大功告成！</span><br><span class="line"> </span><br><span class="line">原因：</span><br><span class="line">NO_ZERO_IN_DATE,NO_ZERO_DATE是无法默认为‘<span class="number">0000</span><span class="number">-00</span><span class="number">-00</span> <span class="number">00</span>:<span class="number">00</span>:<span class="number">00</span>’的根源。</span><br><span class="line">NO_ZERO_IN_DATE：在严格模式下，不允许日期和月份为零 </span><br><span class="line">NO_ZERO_DATE：设置该值，mysql数据库不允许插入零日期，插入零日期会抛出错误而不是警告。</span><br></pre></td></tr></table></figure>
<h3 id="INFORMATION-SCHEMA"><a href="#INFORMATION-SCHEMA" class="headerlink" title="INFORMATION_SCHEMA"></a>INFORMATION_SCHEMA</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">INFORMATION_SCHEMA 是用来访问数据库的元数据（比如数据库，表的名称，列的数据类型或者访问权限等）的，在每个 MySQL 的实例中，INFORMATION_SCHEMA 保存了它维护的所有数据库的信息</span><br><span class="line">查询出数据库 wizard 中所有的表以及数据类型，存储引擎。</span><br><span class="line">使用 INFORMATION_SCHEMA 查询可能会从多个数据库检索信息，所以查询可能会比较耗时，对性能产生一定的影响。在执行之前，可以使用 EXPLAIN 命令检查一下查询的效率</span><br><span class="line">mysql&gt; SELECT table_name, table_type, engine</span><br><span class="line">    -&gt; FROM information_schema.tables</span><br><span class="line">    -&gt; WHERE table_schema = <span class="string">'wizard'</span></span><br><span class="line">    -&gt; ORDER BY table_name;</span><br><span class="line"></span><br><span class="line">https:<span class="comment">//github.com/mylxsw/growing-up/blob/master/doc/mysql-lock-transaction.md  程序猿成长计划</span></span><br><span class="line">https:<span class="comment">//learnku.com/articles/35773</span></span><br></pre></td></tr></table></figure>
<h3 id="Got-error-134-from-storage-engine"><a href="#Got-error-134-from-storage-engine" class="headerlink" title="Got error 134 from storage engine"></a>Got error 134 from storage engine</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"> SELECT * FROM <span class="string">`xx_article`</span> WHERE <span class="string">`cid1`</span>  =<span class="number">6</span> LIMIT <span class="number">0</span>  ,  <span class="number">30</span></span><br><span class="line"></span><br><span class="line">. #1030 - Got error 134 from storage engine</span><br><span class="line">　　这才发现原来是存储引擎发生了错误，知道了原因就来弱弱的修复下：</span><br><span class="line"></span><br><span class="line">　　先 check 表:</span><br><span class="line"></span><br><span class="line">check table <span class="string">`xx_article`</span>;</span><br><span class="line">　　这里需要注意的一点是，check 完表后必须修复之后 才能看到数据，切莫看到数据记录为空，就大惊失色。</span><br><span class="line"></span><br><span class="line">　　然后再修复表：</span><br><span class="line"></span><br><span class="line"> repair  table <span class="string">`xx_article`</span>;</span><br><span class="line">https:<span class="comment">//learnku.com/articles/35836</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL批量更新与插入"><a href="#MySQL批量更新与插入" class="headerlink" title="MySQL批量更新与插入"></a>MySQL批量更新与插入</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line">replace into table （ <span class="string">`column1`</span>,<span class="string">`column2`</span>,<span class="string">`column3`</span> ）values (<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>),(<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>),(<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>)</span><br><span class="line">INSERT INTO t1 (a,b,c) VALUES (<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>)</span><br><span class="line">  ON DUPLICATE KEY UPDATE c=c+<span class="number">1</span>;</span><br><span class="line">UPDATE t1 SET c=c+<span class="number">1</span> WHERE a=<span class="number">1</span>;</span><br><span class="line">update table set </span><br><span class="line">column1 = <span class="keyword">case</span>  when column2 = <span class="number">1</span> then <span class="number">2</span> <span class="keyword">else</span> <span class="number">3</span> end ,</span><br><span class="line">column3 = <span class="keyword">case</span>  when column4 = <span class="number">1</span> then <span class="number">2</span> <span class="keyword">else</span> <span class="number">3</span> end </span><br><span class="line">where id <span class="keyword">in</span> (<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>)</span><br><span class="line"><span class="comment">//拼装按条件批量更新SQL语句</span></span><br><span class="line">protected <span class="function"><span class="keyword">function</span> <span class="title">handleUpdate</span>(<span class="params">$data, $key</span>)</span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (empty($data) || !is_array($data)) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        $keys_array = array_keys(current($data));</span><br><span class="line"></span><br><span class="line"><span class="comment">//需要被更新的字段</span></span><br><span class="line">        $update_column = [</span><br><span class="line">            $keys_array[<span class="number">5</span>],</span><br><span class="line">            $keys_array[<span class="number">6</span>],</span><br><span class="line">            $keys_array[<span class="number">8</span>],</span><br><span class="line">            $keys_array[<span class="number">9</span>],</span><br><span class="line">            $keys_array[<span class="number">16</span>],</span><br><span class="line">            $keys_array[<span class="number">14</span>]</span><br><span class="line">        ];</span><br><span class="line"></span><br><span class="line"><span class="comment">//更新条件</span></span><br><span class="line">        $vehicle_id = $keys_array[<span class="number">2</span>];</span><br><span class="line">        $body_color = $keys_array[<span class="number">3</span>];</span><br><span class="line">        $interior_color = $keys_array[<span class="number">4</span>];</span><br><span class="line">        $city_id = $keys_array[<span class="number">11</span>];</span><br><span class="line">        $province_id = $keys_array[<span class="number">10</span>];</span><br><span class="line"></span><br><span class="line">        $q = <span class="string">"UPDATE ce SET "</span>;</span><br><span class="line">        foreach ($update_column <span class="keyword">as</span> $update_colum) &#123;</span><br><span class="line">            $q .= <span class="string">' '</span> . $update_colum . <span class="string">' = CASE '</span>;</span><br><span class="line">            foreach ($data <span class="keyword">as</span> $value) &#123;</span><br><span class="line">                $value[$update_colum] = !isset($value[$update_colum]) || empty($value[$update_colum])</span><br><span class="line">                    ? <span class="number">0</span> : $value[$update_colum];</span><br><span class="line">                $q .= <span class="string">' when '</span> . $vehicle_id . <span class="string">' ='</span> . $value[$vehicle_id]</span><br><span class="line">                    . <span class="string">' and '</span> . $body_color . <span class="string">' = "'</span> . $value[$body_color] . <span class="string">'"'</span></span><br><span class="line">                    . <span class="string">' and '</span> . $interior_color . <span class="string">' = "'</span> . $value[$interior_color] . <span class="string">'"'</span></span><br><span class="line">                    . <span class="string">' and '</span> . $city_id . <span class="string">' ='</span> . $value[$city_id]</span><br><span class="line">                    . <span class="string">' and '</span> . $province_id . <span class="string">' ='</span> . $value[$province_id] . <span class="string">' then '</span> . $value[$update_colum];</span><br><span class="line">            &#125;</span><br><span class="line">            $q .= <span class="string">" ELSE "</span> . $update_colum . <span class="string">" END, "</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        $q = rtrim($q, <span class="string">", "</span>);</span><br><span class="line">    &#125;</span><br><span class="line">https:<span class="comment">//dalebao.github.io/2019/04/27/MySQL%E6%89%B9%E9%87%8F%E6%9B%B4%E6%96%B0%E4%B8%8E%E6%8F%92%E5%85%A5/</span></span><br></pre></td></tr></table></figure>
<h3 id="恢复误删的数据库"><a href="#恢复误删的数据库" class="headerlink" title="恢复误删的数据库"></a>恢复误删的数据库</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">mysql -h127<span class="number">.0</span><span class="number">.0</span><span class="number">.1</span> -uroot -p del &lt; bak.sql</span><br><span class="line">误删后可以保存下binlog</span><br><span class="line"></span><br><span class="line">mysqlbinlog mysql-bin<span class="number">.000011</span> &gt; del.log</span><br><span class="line">打开文件，去掉drop操作并保存。</span><br><span class="line"></span><br><span class="line">mysql -h127<span class="number">.0</span><span class="number">.0</span><span class="number">.1</span> -uroot -p &lt;del.log</span><br><span class="line">当然，比较建议通过dump全备份操作，然后找出备份到drop的pos。</span><br></pre></td></tr></table></figure>
<h3 id="show-processlist-神器"><a href="#show-processlist-神器" class="headerlink" title="show processlist 神器"></a>show processlist 神器</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">SELECT id, db, USER, HOST, command, time, state, info FROM information_schema. PROCESSLIST WHERE command != <span class="string">'Sleep'</span> ORDER BY time DESC;</span><br><span class="line">mysql&gt; show full processlist;</span><br><span class="line">+--------+------+----------------------+-------+---------+------+----------+-----------------------+</span><br><span class="line">| Id     | User | Host                 | db    | Command | Time | State    | Info                  |</span><br><span class="line">+--------+------+----------------------+-------+---------+------+----------+-----------------------+</span><br><span class="line">| <span class="number">449000</span> | root | <span class="number">127.123</span><span class="number">.213</span><span class="number">.11</span>:<span class="number">59828</span> | stark | Sleep   | <span class="number">1270</span> |          | NULL                  |</span><br><span class="line"></span><br><span class="line">-- 查询执行时间超过<span class="number">3</span>分钟的线程，然后拼接成 kill 语句</span><br><span class="line">select concat(<span class="string">'kill '</span>, id, <span class="string">';'</span>)</span><br><span class="line"><span class="keyword">from</span> information_schema.processlist</span><br><span class="line">where command != <span class="string">'Sleep'</span></span><br><span class="line">and time &gt; <span class="number">3</span>*<span class="number">60</span></span><br><span class="line">order by time desc;</span><br><span class="line">https:<span class="comment">//learnku.com/articles/36035</span></span><br></pre></td></tr></table></figure>
<h3 id="like-条件的优化"><a href="#like-条件的优化" class="headerlink" title="like 条件的优化"></a>like 条件的优化</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">like 语句查询慢的可以尝试使用函数来查询，具体为 instr (字段名，<span class="string">' 值 '</span>)&gt;<span class="number">0</span></span><br><span class="line">比如查询包含 “钟” 字的，instr (name, <span class="string">' 钟 '</span>) &gt; <span class="number">0</span></span><br><span class="line">使用该函数后，查询仅需 <span class="number">0.031</span>s</span><br><span class="line">https:<span class="comment">//learnku.com/articles/36187</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL事务隔离"><a href="#MySQL事务隔离" class="headerlink" title="MySQL事务隔离"></a>MySQL事务隔离</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br></pre></td><td class="code"><pre><span class="line">事务就是一组原子性的sql查询，或者说是一个独立的工作单元。简而言之，事务内的语句要么全部执行成功，要么全部执行失败。</span><br><span class="line"></span><br><span class="line">在Mysql中，事务支持是在引擎层实现的，但并不是所有的Mysql引擎都支持事务，比如MyISAM引擎就不支持事务，这也是MyISAM被InnoDB取代的重要原因之一。</span><br><span class="line"></span><br><span class="line">提到事务，我们肯定会想到ACID：</span><br><span class="line"></span><br><span class="line">原子性(Atomicity)</span><br><span class="line">一致性(Consistency)</span><br><span class="line">隔离性(Isolation)</span><br><span class="line">持久性(Durability)</span><br><span class="line">隔离级别</span><br><span class="line">当数据库中有多个事务同时执行时，就可能会出现脏读、不可重复读、幻读等问题，因为就有了事务隔离级别的概念。</span><br><span class="line"></span><br><span class="line">SQL标准正定义了四种隔离级别：</span><br><span class="line"></span><br><span class="line">READ UNCOMMITTED (未提交读)</span><br><span class="line"></span><br><span class="line">事务中的修改，即使还没有提交，对其他事务都是可见的。事务可以读取未提交的数据，也被称为脏读(Dirty Read)。</span><br><span class="line"></span><br><span class="line">READ COMMITTED(提交读)</span><br><span class="line"></span><br><span class="line">一个事务提交后，所做的变更才能被其他事务看到。这个级别也叫不可重复读，因为事务中执行<span class="number">2</span>次相同的查询，可能得到的结果是不一样的。</span><br><span class="line"></span><br><span class="line">REPEATABLE READ(可重复读)</span><br><span class="line"></span><br><span class="line">一个事务执行的过程中，总是和这个事务在启动时看到的数据是一致的。当然在这个级别下，未提交的数据变更对其他事务也是不可见的。</span><br><span class="line"></span><br><span class="line">SERIALIZABLE(可串行化)</span><br><span class="line"></span><br><span class="line">对同一行记录，写和读都会加锁，当出现读写锁冲突时，后访问的事务必须等前一个事务执行完成才能继续执行，就会导致大量的超时和锁争用的问题。</span><br><span class="line"></span><br><span class="line">在实现上，数据库里面会创建一个视图，访问的时候以视图的逻辑为准。</span><br><span class="line"></span><br><span class="line">在可重复读这个隔离级别下，这个视图是事务开启的时候创建的，整个事务期间都用这个视图。</span><br><span class="line"></span><br><span class="line">在读提交的隔离级别下，这个视图是在sql语句开始执行的时候创建的。</span><br><span class="line"></span><br><span class="line">在读未提交的隔离级别下，直接返回记录上的最新值，没有视图概念。</span><br><span class="line"></span><br><span class="line">在串行化的隔离级别下，直接用加锁的方式避免并行访问。</span><br><span class="line"></span><br><span class="line">配置的方式是将启动参数transaction-isolation设置成想要的隔离级别。</span><br><span class="line"></span><br><span class="line">查看当前设置：</span><br><span class="line"></span><br><span class="line">mysql&gt; show variables like <span class="string">'transaction_isolation'</span>;</span><br><span class="line">+-----------------------+-----------------+</span><br><span class="line">| Variable_name         | Value           |</span><br><span class="line">+-----------------------+-----------------+</span><br><span class="line">| transaction_isolation | REPEATABLE-READ |</span><br><span class="line">+-----------------------+-----------------+</span><br><span class="line"><span class="number">1</span> row <span class="keyword">in</span> set (<span class="number">0.00</span> sec)</span><br><span class="line"></span><br><span class="line">总之，存在即合理，不同的隔离级别适用于不同的场景，具体我们应该根据业务场景来决定。</span><br><span class="line"></span><br><span class="line">事务隔离的实现</span><br><span class="line">在Mysql中，实际上每条记录的更新同时也会记录一条回滚操作，记录上的最新值通过回滚操作，都可以得到前一个状态的值。</span><br><span class="line"></span><br><span class="line">系统会自动判断，当没有事务再需要回滚日志时，会删除回滚日志。</span><br><span class="line"></span><br><span class="line">为什么不建议使用长事务：</span><br><span class="line"></span><br><span class="line">长事务意味着系统里面会存在很老的事务视图，由于这些事务随时可以访问数据库里面的任何数据，所以这个事务提交之前，数据库里可能用到的回滚记录必须保留着，这就会占用大量的存储空间。同时长事务还占用锁资源，也可能拖垮整个库。</span><br><span class="line"></span><br><span class="line">事务启动的方式</span><br><span class="line">显式启动事务语句，begin或者start transaction,提交就是commit,回滚用rollback。</span><br><span class="line">set autocommit = <span class="number">0</span>,这个命令会将线程的自动提交关掉，意味着如果执行一个select 语句，这个事务就启动了，并且不会自动提交，直到你主动执行commit或者rollback，或者断开连接。</span><br><span class="line">个人建议还是通过第一种方式显式启动事务，避免长事务的发生。</span><br><span class="line"></span><br><span class="line">在 set autocommit = <span class="number">1</span> 的情况下，用 begin 显式启动的事务，如果执行 commit 则提交事务。如果执行 commit work and chain，则是提交事务并自动启动下一个事务，这样也省去了再次执行 begin 语句的开销。</span><br><span class="line"></span><br><span class="line">查询长事务：</span><br><span class="line"></span><br><span class="line">下面语句是查询持续时间超过<span class="number">60</span>s的事务</span><br><span class="line"></span><br><span class="line">mysql&gt; select * <span class="keyword">from</span> information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))&gt;<span class="number">60</span>;</span><br><span class="line">Empty set (<span class="number">0.00</span> sec)</span><br><span class="line">总结下来，我们在开发过程中，尽量少用长事务，如果无法避免，保证逻辑日志空间足够大，并且支持动态日志空间增长。监控Innodb_trx表，发现长事务报警</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> https:<span class="comment">//tsmliyun.github.io/mysql/MySQL%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB/</span></span><br></pre></td></tr></table></figure>
<h3 id="后台权限表"><a href="#后台权限表" class="headerlink" title="后台权限表"></a>后台权限表</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br></pre></td><td class="code"><pre><span class="line">DROP TABLE IF EXISTS <span class="string">`crm_admin_permission`</span>;</span><br><span class="line"></span><br><span class="line">CREATE TABLE <span class="string">`crm_admin_permission`</span> (</span><br><span class="line">  <span class="string">`id`</span> int(<span class="number">10</span>) unsigned NOT NULL AUTO_INCREMENT,</span><br><span class="line">  <span class="string">`parent_id`</span> int(<span class="number">11</span>) NOT NULL DEFAULT <span class="number">0</span>,</span><br><span class="line">  <span class="string">`title`</span> varchar(<span class="number">50</span>) NOT NULL DEFAULT <span class="string">''</span> COMMENT <span class="string">'标题'</span>,</span><br><span class="line">  <span class="string">`icon`</span> varchar(<span class="number">50</span>) NOT NULL DEFAULT <span class="string">''</span>,</span><br><span class="line">  <span class="string">`path`</span> varchar(<span class="number">50</span>) NOT NULL DEFAULT <span class="string">''</span> COMMENT <span class="string">'路由'</span>,</span><br><span class="line">  <span class="string">`is_menu`</span> tinyint(<span class="number">4</span>) NOT NULL DEFAULT <span class="number">0</span> COMMENT <span class="string">'是否是菜单,1=&gt;是,0=&gt;否'</span>,</span><br><span class="line">  <span class="string">`sort`</span> int(<span class="number">11</span>) NOT NULL DEFAULT <span class="number">0</span> COMMENT <span class="string">'排序'</span>,</span><br><span class="line">  <span class="string">`level`</span> tinyint(<span class="number">4</span>) NOT NULL DEFAULT <span class="number">0</span> COMMENT <span class="string">'等级'</span>,</span><br><span class="line">  <span class="string">`status`</span> tinyint(<span class="number">4</span>) NOT NULL DEFAULT <span class="number">1</span> COMMENT <span class="string">'状态 1=&gt;启用 0=&gt;禁用'</span>,</span><br><span class="line">  <span class="string">`created_at`</span> timestamp NOT NULL DEFAULT <span class="string">'0000-00-00 00:00:00'</span>,</span><br><span class="line">  <span class="string">`updated_at`</span> timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,</span><br><span class="line">  PRIMARY KEY (<span class="string">`id`</span>),</span><br><span class="line">  KEY <span class="string">`idx_parent_id`</span> (<span class="string">`parent_id`</span>),</span><br><span class="line">  KEY <span class="string">`idx_path`</span> (<span class="string">`path`</span>)</span><br><span class="line">) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=<span class="string">'菜单表'</span>;</span><br><span class="line"></span><br><span class="line">LOCK TABLES <span class="string">`crm_admin_permission`</span> WRITE;</span><br><span class="line"><span class="comment">/*!40000 ALTER TABLE `crm_admin_permission` DISABLE KEYS */</span>;</span><br><span class="line"></span><br><span class="line">INSERT INTO <span class="string">`crm_admin_permission`</span> (<span class="string">`id`</span>, <span class="string">`parent_id`</span>, <span class="string">`title`</span>, <span class="string">`icon`</span>, <span class="string">`path`</span>, <span class="string">`is_menu`</span>, <span class="string">`sort`</span>, <span class="string">`level`</span>, <span class="string">`status`</span>, <span class="string">`created_at`</span>, <span class="string">`updated_at`</span>)</span><br><span class="line">VALUES</span><br><span class="line">	(<span class="number">23</span>,<span class="number">0</span>,<span class="string">'管理员管理'</span>,<span class="string">''</span>,<span class="string">''</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="string">'2019-05-20 18:37:40'</span>,<span class="string">'2019-05-20 18:37:40'</span>),</span><br><span class="line">	(<span class="number">24</span>,<span class="number">23</span>,<span class="string">'管理员列表'</span>,<span class="string">''</span>,<span class="string">'admin/admin/lists'</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">1</span>,<span class="string">'2019-05-20 18:38:31'</span>,<span class="string">'2019-05-20 18:38:31'</span>),</span><br><span class="line">	(<span class="number">25</span>,<span class="number">23</span>,<span class="string">'角色管理'</span>,<span class="string">''</span>,<span class="string">'admin/role/lists'</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">2</span>,<span class="number">1</span>,<span class="string">'2019-05-20 18:38:59'</span>,<span class="string">'2019-05-20 18:38:59'</span>),</span><br><span class="line">	(<span class="number">26</span>,<span class="number">23</span>,<span class="string">'权限管理'</span>,<span class="string">''</span>,<span class="string">'admin/permission/lists'</span>,<span class="number">1</span>,<span class="number">3</span>,<span class="number">2</span>,<span class="number">1</span>,<span class="string">'2019-05-20 18:39:36'</span>,<span class="string">'2019-05-20 18:39:36'</span>),</span><br><span class="line">	(<span class="number">27</span>,<span class="number">24</span>,<span class="string">'添加管理员'</span>,<span class="string">''</span>,<span class="string">'admin/admin/create'</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">3</span>,<span class="number">1</span>,<span class="string">'2019-05-20 18:41:44'</span>,<span class="string">'2019-05-20 18:41:44'</span>),</span><br><span class="line">	(<span class="number">28</span>,<span class="number">24</span>,<span class="string">'编辑管理员'</span>,<span class="string">''</span>,<span class="string">'admin/admin/edit'</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">3</span>,<span class="number">1</span>,<span class="string">'2019-05-20 18:42:33'</span>,<span class="string">'2019-05-20 18:42:33'</span>),</span><br><span class="line">	(<span class="number">29</span>,<span class="number">25</span>,<span class="string">'新增角色'</span>,<span class="string">''</span>,<span class="string">'admin/role/create'</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">3</span>,<span class="number">1</span>,<span class="string">'2019-05-20 18:43:42'</span>,<span class="string">'2019-05-20 18:46:29'</span>),</span><br><span class="line">	(<span class="number">30</span>,<span class="number">25</span>,<span class="string">'编辑角色'</span>,<span class="string">''</span>,<span class="string">'admin/role/edit'</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">3</span>,<span class="number">1</span>,<span class="string">'2019-05-20 18:44:21'</span>,<span class="string">'2019-05-20 18:46:30'</span>),</span><br><span class="line">	(<span class="number">36</span>,<span class="number">25</span>,<span class="string">'赋权'</span>,<span class="string">''</span>,<span class="string">'admin/role/permission'</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">3</span>,<span class="number">1</span>,<span class="string">'2019-05-20 18:46:49'</span>,<span class="string">'2019-05-20 19:00:29'</span>),</span><br><span class="line">	(<span class="number">37</span>,<span class="number">25</span>,<span class="string">'赋权-提交'</span>,<span class="string">''</span>,<span class="string">'admin/role/updatePermission'</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">3</span>,<span class="number">1</span>,<span class="string">'2019-05-20 18:47:10'</span>,<span class="string">'2019-05-20 18:47:10'</span>),</span><br><span class="line">	(<span class="number">31</span>,<span class="number">26</span>,<span class="string">'新增权限'</span>,<span class="string">''</span>,<span class="string">'admin/permission/create'</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">3</span>,<span class="number">1</span>,<span class="string">'2019-05-20 18:46:49'</span>,<span class="string">'2019-05-20 19:00:29'</span>),</span><br><span class="line">	(<span class="number">32</span>,<span class="number">26</span>,<span class="string">'编辑权限'</span>,<span class="string">''</span>,<span class="string">'admin/permission/edit'</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">3</span>,<span class="number">1</span>,<span class="string">'2019-05-20 18:47:10'</span>,<span class="string">'2019-05-20 18:47:10'</span>),</span><br><span class="line">	(<span class="number">33</span>,<span class="number">0</span>,<span class="string">'首页'</span>,<span class="string">''</span>,<span class="string">'admin/index'</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="string">'2019-05-20 23:51:37'</span>,<span class="string">'2019-05-20 23:51:47'</span>),</span><br><span class="line">	(<span class="number">34</span>,<span class="number">26</span>,<span class="string">'新增权限-提交'</span>,<span class="string">''</span>,<span class="string">'admin/permission/store'</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">3</span>,<span class="number">1</span>,<span class="string">'2019-05-21 14:38:36'</span>,<span class="string">'2019-05-21 14:38:36'</span>),</span><br><span class="line">	(<span class="number">35</span>,<span class="number">26</span>,<span class="string">'编辑权限-提交'</span>,<span class="string">''</span>,<span class="string">'admin/permission/update'</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">3</span>,<span class="number">1</span>,<span class="string">'2019-05-21 14:38:57'</span>,<span class="string">'2019-05-21 14:38:57'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">/*!40000 ALTER TABLE `crm_admin_permission` ENABLE KEYS */</span>;</span><br><span class="line">UNLOCK TABLES;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># Dump of table crm_admin_role</span><br><span class="line"># ------------------------------------------------------------</span><br><span class="line"></span><br><span class="line">DROP TABLE IF EXISTS <span class="string">`crm_admin_role`</span>;</span><br><span class="line"></span><br><span class="line">CREATE TABLE <span class="string">`crm_admin_role`</span> (</span><br><span class="line">  <span class="string">`id`</span> int(<span class="number">10</span>) unsigned NOT NULL AUTO_INCREMENT,</span><br><span class="line">  <span class="string">`name`</span> varchar(<span class="number">50</span>) NOT NULL DEFAULT <span class="string">''</span> COMMENT <span class="string">'角色名称'</span>,</span><br><span class="line">  <span class="string">`status`</span> tinyint(<span class="number">4</span>) NOT NULL DEFAULT <span class="number">1</span> COMMENT <span class="string">'状态 1=&gt;启用 0=&gt;禁用'</span>,</span><br><span class="line">  <span class="string">`created_at`</span> timestamp NOT NULL DEFAULT <span class="string">'0000-00-00 00:00:00'</span>,</span><br><span class="line">  <span class="string">`updated_at`</span> timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,</span><br><span class="line">  PRIMARY KEY (<span class="string">`id`</span>),</span><br><span class="line">  UNIQUE KEY <span class="string">`unk_name`</span> (<span class="string">`name`</span>)</span><br><span class="line">) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=<span class="string">'角色表'</span>;</span><br><span class="line"></span><br><span class="line">LOCK TABLES <span class="string">`crm_admin_role`</span> WRITE;</span><br><span class="line"><span class="comment">/*!40000 ALTER TABLE `crm_admin_role` DISABLE KEYS */</span>;</span><br><span class="line"></span><br><span class="line">INSERT INTO <span class="string">`crm_admin_role`</span> (<span class="string">`id`</span>, <span class="string">`name`</span>, <span class="string">`status`</span>, <span class="string">`created_at`</span>, <span class="string">`updated_at`</span>)</span><br><span class="line">VALUES</span><br><span class="line">	(<span class="number">1</span>,<span class="string">'超级管理员'</span>,<span class="number">1</span>,<span class="string">'2019-05-06 18:52:06'</span>,<span class="string">'2019-05-07 16:56:26'</span>),</span><br><span class="line">	(<span class="number">2</span>,<span class="string">'普通管理员'</span>,<span class="number">1</span>,<span class="string">'2019-05-06 18:52:29'</span>,<span class="string">'2019-05-06 18:52:29'</span>),</span><br><span class="line">	(<span class="number">8</span>,<span class="string">'开发'</span>,<span class="number">1</span>,<span class="string">'2019-05-20 16:50:40'</span>,<span class="string">'2019-05-20 16:50:40'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">/*!40000 ALTER TABLE `crm_admin_role` ENABLE KEYS */</span>;</span><br><span class="line">UNLOCK TABLES;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># Dump of table crm_admin_role_permission</span><br><span class="line"># ------------------------------------------------------------</span><br><span class="line"></span><br><span class="line">DROP TABLE IF EXISTS <span class="string">`crm_admin_role_permission`</span>;</span><br><span class="line"></span><br><span class="line">CREATE TABLE <span class="string">`crm_admin_role_permission`</span> (</span><br><span class="line">  <span class="string">`id`</span> int(<span class="number">10</span>) unsigned NOT NULL AUTO_INCREMENT,</span><br><span class="line">  <span class="string">`role_id`</span> int(<span class="number">11</span>) NOT NULL DEFAULT <span class="number">0</span>,</span><br><span class="line">  <span class="string">`permission_id`</span> int(<span class="number">11</span>) NOT NULL DEFAULT <span class="number">0</span>,</span><br><span class="line">  <span class="string">`created_at`</span> timestamp NOT NULL DEFAULT <span class="string">'0000-00-00 00:00:00'</span>,</span><br><span class="line">  <span class="string">`updated_at`</span> timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,</span><br><span class="line">  PRIMARY KEY (<span class="string">`id`</span>),</span><br><span class="line">  KEY <span class="string">`idx_role_id`</span> (<span class="string">`role_id`</span>),</span><br><span class="line">  KEY <span class="string">`idx_permission_id`</span> (<span class="string">`permission_id`</span>)</span><br><span class="line">) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=<span class="string">'角色权限关联表'</span>;</span><br><span class="line"></span><br><span class="line">LOCK TABLES <span class="string">`crm_admin_role_permission`</span> WRITE;</span><br><span class="line"><span class="comment">/*!40000 ALTER TABLE `crm_admin_role_permission` DISABLE KEYS */</span>;</span><br><span class="line"></span><br><span class="line">INSERT INTO <span class="string">`crm_admin_role_permission`</span> (<span class="string">`id`</span>, <span class="string">`role_id`</span>, <span class="string">`permission_id`</span>, <span class="string">`created_at`</span>, <span class="string">`updated_at`</span>)</span><br><span class="line">VALUES</span><br><span class="line">	(<span class="number">12</span>,<span class="number">2</span>,<span class="number">20</span>,<span class="string">'2019-05-20 18:04:36'</span>,<span class="string">'2019-05-20 18:04:36'</span>),</span><br><span class="line">	(<span class="number">13</span>,<span class="number">2</span>,<span class="number">21</span>,<span class="string">'2019-05-20 18:04:36'</span>,<span class="string">'2019-05-20 18:04:36'</span>),</span><br><span class="line">	(<span class="number">14</span>,<span class="number">2</span>,<span class="number">22</span>,<span class="string">'2019-05-20 18:04:36'</span>,<span class="string">'2019-05-20 18:04:36'</span>),</span><br><span class="line">	(<span class="number">26</span>,<span class="number">1</span>,<span class="number">23</span>,<span class="string">'2019-05-21 14:39:34'</span>,<span class="string">'2019-05-21 14:39:34'</span>),</span><br><span class="line">	(<span class="number">27</span>,<span class="number">1</span>,<span class="number">24</span>,<span class="string">'2019-05-21 14:39:34'</span>,<span class="string">'2019-05-21 14:39:34'</span>),</span><br><span class="line">	(<span class="number">28</span>,<span class="number">1</span>,<span class="number">27</span>,<span class="string">'2019-05-21 14:39:34'</span>,<span class="string">'2019-05-21 14:39:34'</span>),</span><br><span class="line">	(<span class="number">29</span>,<span class="number">1</span>,<span class="number">28</span>,<span class="string">'2019-05-21 14:39:34'</span>,<span class="string">'2019-05-21 14:39:34'</span>),</span><br><span class="line">	(<span class="number">30</span>,<span class="number">1</span>,<span class="number">25</span>,<span class="string">'2019-05-21 14:39:34'</span>,<span class="string">'2019-05-21 14:39:34'</span>),</span><br><span class="line">	(<span class="number">31</span>,<span class="number">1</span>,<span class="number">29</span>,<span class="string">'2019-05-21 14:39:34'</span>,<span class="string">'2019-05-21 14:39:34'</span>),</span><br><span class="line">	(<span class="number">32</span>,<span class="number">1</span>,<span class="number">30</span>,<span class="string">'2019-05-21 14:39:34'</span>,<span class="string">'2019-05-21 14:39:34'</span>),</span><br><span class="line">	(<span class="number">33</span>,<span class="number">1</span>,<span class="number">26</span>,<span class="string">'2019-05-21 14:39:34'</span>,<span class="string">'2019-05-21 14:39:34'</span>),</span><br><span class="line">	(<span class="number">34</span>,<span class="number">1</span>,<span class="number">31</span>,<span class="string">'2019-05-21 14:39:34'</span>,<span class="string">'2019-05-21 14:39:34'</span>),</span><br><span class="line">	(<span class="number">35</span>,<span class="number">1</span>,<span class="number">32</span>,<span class="string">'2019-05-21 14:39:34'</span>,<span class="string">'2019-05-21 14:39:34'</span>),</span><br><span class="line">	(<span class="number">36</span>,<span class="number">1</span>,<span class="number">34</span>,<span class="string">'2019-05-21 14:39:34'</span>,<span class="string">'2019-05-21 14:39:34'</span>),</span><br><span class="line">	(<span class="number">37</span>,<span class="number">1</span>,<span class="number">35</span>,<span class="string">'2019-05-21 14:39:34'</span>,<span class="string">'2019-05-21 14:39:34'</span>),</span><br><span class="line">	(<span class="number">38</span>,<span class="number">1</span>,<span class="number">33</span>,<span class="string">'2019-05-21 14:39:34'</span>,<span class="string">'2019-05-21 14:39:34'</span>),</span><br><span class="line">	(<span class="number">39</span>,<span class="number">1</span>,<span class="number">36</span>,<span class="string">'2019-05-21 14:39:34'</span>,<span class="string">'2019-05-21 14:39:34'</span>),</span><br><span class="line">	(<span class="number">40</span>,<span class="number">1</span>,<span class="number">37</span>,<span class="string">'2019-05-21 14:39:34'</span>,<span class="string">'2019-05-21 14:39:34'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">/*!40000 ALTER TABLE `crm_admin_role_permission` ENABLE KEYS */</span>;</span><br><span class="line">UNLOCK TABLES;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># Dump of table crm_admin_user</span><br><span class="line"># ------------------------------------------------------------</span><br><span class="line"></span><br><span class="line">DROP TABLE IF EXISTS <span class="string">`crm_admin_user`</span>;</span><br><span class="line"></span><br><span class="line">CREATE TABLE <span class="string">`crm_admin_user`</span> (</span><br><span class="line">  <span class="string">`id`</span> int(<span class="number">10</span>) unsigned NOT NULL AUTO_INCREMENT,</span><br><span class="line">  <span class="string">`username`</span> varchar(<span class="number">32</span>) NOT NULL DEFAULT <span class="string">''</span> COMMENT <span class="string">'登陆的用户名'</span>,</span><br><span class="line">  <span class="string">`email`</span> varchar(<span class="number">32</span>) NOT NULL DEFAULT <span class="string">''</span> COMMENT <span class="string">'email'</span>,</span><br><span class="line">  <span class="string">`phone`</span> char(<span class="number">11</span>) NOT NULL DEFAULT <span class="string">''</span> COMMENT <span class="string">'电话号码'</span>,</span><br><span class="line">  <span class="string">`password`</span> char(<span class="number">60</span>) NOT NULL DEFAULT <span class="string">''</span> COMMENT <span class="string">'密码'</span>,</span><br><span class="line">  <span class="string">`status`</span> tinyint(<span class="number">4</span>) NOT NULL DEFAULT <span class="number">1</span> COMMENT <span class="string">'1 =&gt; 启用 0=&gt;禁用'</span>,</span><br><span class="line">  <span class="string">`created_at`</span> timestamp NOT NULL DEFAULT <span class="string">'0000-00-00 00:00:00'</span>,</span><br><span class="line">  <span class="string">`updated_at`</span> timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,</span><br><span class="line">  <span class="string">`deleted_at`</span> datetime DEFAULT NULL,</span><br><span class="line">  PRIMARY KEY (<span class="string">`id`</span>),</span><br><span class="line">  UNIQUE KEY <span class="string">`uk_email`</span> (<span class="string">`email`</span>) USING BTREE</span><br><span class="line">) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=<span class="string">'管理员信息表'</span>;</span><br><span class="line"></span><br><span class="line">LOCK TABLES <span class="string">`crm_admin_user`</span> WRITE;</span><br><span class="line"><span class="comment">/*!40000 ALTER TABLE `crm_admin_user` DISABLE KEYS */</span>;</span><br><span class="line"></span><br><span class="line">INSERT INTO <span class="string">`crm_admin_user`</span> (<span class="string">`id`</span>, <span class="string">`username`</span>, <span class="string">`email`</span>, <span class="string">`phone`</span>, <span class="string">`password`</span>, <span class="string">`status`</span>, <span class="string">`created_at`</span>, <span class="string">`updated_at`</span>, <span class="string">`deleted_at`</span>)</span><br><span class="line">VALUES</span><br><span class="line">	(<span class="number">27</span>,<span class="string">'li12312'</span>,<span class="string">'1234@qq.com'</span>,<span class="string">'15111179935'</span>,<span class="string">'$2y$10$LFQrR5PWcsxSTYhNYG1tK.IipQHjiJsVakluH4F0iDK50rtUTMVfq'</span>,<span class="number">1</span>,<span class="string">'2019-05-20 00:17:56'</span>,<span class="string">'2019-05-20 11:45:59'</span>,NULL);</span><br><span class="line"></span><br><span class="line"><span class="comment">/*!40000 ALTER TABLE `crm_admin_user` ENABLE KEYS */</span>;</span><br><span class="line">UNLOCK TABLES;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># Dump of table crm_admin_user_role</span><br><span class="line"># ------------------------------------------------------------</span><br><span class="line"></span><br><span class="line">DROP TABLE IF EXISTS <span class="string">`crm_admin_user_role`</span>;</span><br><span class="line"></span><br><span class="line">CREATE TABLE <span class="string">`crm_admin_user_role`</span> (</span><br><span class="line">  <span class="string">`id`</span> int(<span class="number">10</span>) unsigned NOT NULL AUTO_INCREMENT,</span><br><span class="line">  <span class="string">`user_id`</span> int(<span class="number">11</span>) NOT NULL DEFAULT <span class="number">0</span>,</span><br><span class="line">  <span class="string">`role_id`</span> int(<span class="number">11</span>) NOT NULL DEFAULT <span class="number">0</span>,</span><br><span class="line">  <span class="string">`created_at`</span> timestamp NOT NULL DEFAULT <span class="string">'0000-00-00 00:00:00'</span>,</span><br><span class="line">  <span class="string">`updated_at`</span> timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,</span><br><span class="line">  PRIMARY KEY (<span class="string">`id`</span>),</span><br><span class="line">  KEY <span class="string">`idx_user_id`</span> (<span class="string">`user_id`</span>),</span><br><span class="line">  KEY <span class="string">`idx_role_id`</span> (<span class="string">`role_id`</span>)</span><br><span class="line">) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=<span class="string">'用户角色关联表'</span>;</span><br><span class="line"></span><br><span class="line">LOCK TABLES <span class="string">`crm_admin_user_role`</span> WRITE;</span><br><span class="line"><span class="comment">/*!40000 ALTER TABLE `crm_admin_user_role` DISABLE KEYS */</span>;</span><br><span class="line"></span><br><span class="line">INSERT INTO <span class="string">`crm_admin_user_role`</span> (<span class="string">`id`</span>, <span class="string">`user_id`</span>, <span class="string">`role_id`</span>, <span class="string">`created_at`</span>, <span class="string">`updated_at`</span>)</span><br><span class="line">VALUES</span><br><span class="line">	(<span class="number">1</span>,<span class="number">13</span>,<span class="number">1</span>,<span class="string">'2019-05-07 15:45:55'</span>,<span class="string">'2019-05-07 15:45:55'</span>),</span><br><span class="line">	(<span class="number">9</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="string">'2019-05-07 16:33:18'</span>,<span class="string">'2019-05-07 16:33:18'</span>),</span><br><span class="line">	(<span class="number">13</span>,<span class="number">27</span>,<span class="number">1</span>,<span class="string">'2019-05-20 10:37:04'</span>,<span class="string">'2019-05-20 10:37:04'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">/*!40000 ALTER TABLE `crm_admin_user_role` ENABLE KEYS */</span>;</span><br><span class="line">UNLOCK TABLES;</span><br><span class="line">https:<span class="comment">//github.com/tsmliyun/laravel_quick_admin</span></span><br></pre></td></tr></table></figure>
<h3 id="取分组数据的前N条纪录"><a href="#取分组数据的前N条纪录" class="headerlink" title="取分组数据的前N条纪录"></a>取分组数据的前N条纪录</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line">CREATE TABLE tbl ( cate  varchar(<span class="number">10</span>), item  int, note varchar(<span class="number">20</span>));</span><br><span class="line">INSERT INTO tbl VALUES</span><br><span class="line">    (<span class="string">'a'</span>, <span class="number">2</span>, <span class="string">'a的第二个值'</span>),</span><br><span class="line">    (<span class="string">'a'</span>, <span class="number">1</span>, <span class="string">'a的第一个值'</span>),</span><br><span class="line">    (<span class="string">'a'</span>, <span class="number">3</span>, <span class="string">'a的第三个值'</span>),</span><br><span class="line">    (<span class="string">'b'</span>, <span class="number">1</span>, <span class="string">'b的第一个值'</span>),</span><br><span class="line">    (<span class="string">'b'</span>, <span class="number">3</span>, <span class="string">'b的第三个值'</span>),</span><br><span class="line">    (<span class="string">'b'</span>, <span class="number">2</span>, <span class="string">'b的第二个值'</span>),</span><br><span class="line">    (<span class="string">'b'</span>, <span class="number">4</span>, <span class="string">'b的第四个值'</span>),</span><br><span class="line">    (<span class="string">'b'</span>, <span class="number">5</span>, <span class="string">'b的第五个值'</span>);</span><br><span class="line">取每个 cate item 最大/最小的那条记录</span><br><span class="line"></span><br><span class="line">mysql&gt; SELECT a.* FROM tbl a WHERE item = (</span><br><span class="line">    -&gt; SELECT MAX(item) FROM tbl WHERE cate = a.cate</span><br><span class="line">    -&gt; ) ORDER BY a.cate;</span><br><span class="line">+------+------+------------------+</span><br><span class="line">| cate | item | note             |</span><br><span class="line">+------+------+------------------+</span><br><span class="line">| a    |    <span class="number">3</span> | a的第三个值      |</span><br><span class="line">| b    |    <span class="number">5</span> | b的第五个值      |</span><br><span class="line">+------+------+------------------+</span><br><span class="line"><span class="number">2</span> rows <span class="keyword">in</span> set (<span class="number">0.01</span> sec)</span><br><span class="line">按 cate 分组取最大/最小的两个(N个)item</span><br><span class="line"></span><br><span class="line">mysql&gt; SELECT a.* FROM tbl a WHERE EXISTS (</span><br><span class="line">    -&gt; SELECT COUNT(*) FROM tbl</span><br><span class="line">    -&gt; WHERE cate = a.cate AND item &lt; a.item HAVING COUNT(*) &lt; <span class="number">2</span></span><br><span class="line">    -&gt; ) ORDER BY a.cate, a.item;</span><br><span class="line">+------+------+------------------+</span><br><span class="line">| cate | item | note             |</span><br><span class="line">+------+------+------------------+</span><br><span class="line">| a    |    <span class="number">1</span> | a的第一个值      |</span><br><span class="line">| a    |    <span class="number">2</span> | a的第二个值      |</span><br><span class="line">| b    |    <span class="number">1</span> | b的第一个值      |</span><br><span class="line">| b    |    <span class="number">2</span> | b的第二个值      |</span><br><span class="line">+------+------+------------------+</span><br><span class="line"><span class="number">4</span> rows <span class="keyword">in</span> set (<span class="number">0.00</span> sec)</span><br><span class="line">select </span><br><span class="line"><span class="keyword">from</span> table a</span><br><span class="line">where <span class="number">2</span>&gt;(select count() <span class="keyword">from</span> table where bind_category_id=a.bind_category_idand created_at&gt;a.created_at)</span><br><span class="line">order by a.bind_category_idand ,a.created_at desc</span><br><span class="line">https:<span class="comment">//learnku.com/laravel/t/36766</span></span><br><span class="line">https:<span class="comment">//n3xtchen.github.io/n3xtchen/postgresql/2015/08/13/pgsql-vs-mysql-get-nth-value-per-group</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL-定时备份"><a href="#MySQL-定时备份" class="headerlink" title="MySQL 定时备份"></a>MySQL 定时备份</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line">backupdir=<span class="regexp">/data/</span>backup</span><br><span class="line">time=<span class="string">`date +%Y-%m-%d-%H-%M`</span></span><br><span class="line"><span class="keyword">if</span>  [ ! -e  /data/backcup  ];then</span><br><span class="line"> mkdir  -p  /data/backup</span><br><span class="line">fi</span><br><span class="line">/usr/bin/mysqldump  --single-transaction  --flush-logs --skip-add-drop-table  -uroot  -p<span class="string">'root@xx'</span>  数据库  |bzip2 &gt; $backupdir/数据库$time.sql.bz2</span><br><span class="line"></span><br><span class="line"># 清理超过7天没使用的文件</span><br><span class="line">find $backupdir -name <span class="string">"数据库*.sql.bz2"</span> -type f -mtime +<span class="number">7</span> -exec rm &#123;&#125; \; &gt; <span class="regexp">/dev/</span><span class="literal">null</span> <span class="number">2</span>&gt;&amp;<span class="number">1</span></span><br><span class="line"></span><br><span class="line">批注：</span><br><span class="line">--single-transaction参数的作用，设置事务的隔离级别为可重复读，即REPEATABLE READ，这样能保证在一个事务中所有相同的查询读取到同样的数据，也就大概保证了在dump期间，如果其他innodb引擎的线程修改了表的数据并提交，对该dump线程的数据并无影响</span><br><span class="line">--skip-add-drop-table  ---取消每个数据表创建之前添加drop数据表语句(默认每个表之前存在drop语句)</span><br><span class="line">--flush-logs  在开始导出前刷新服务器的日志文件</span><br><span class="line">最后导出的数据库备份文件 就是这个 xx2019<span class="number">-11</span><span class="number">-14</span><span class="number">-02</span><span class="number">-00.</span>sql.bz2</span><br><span class="line">mysql -u 用户名 -p密码 数据库名 &lt; 备份文件.sql  恢复某个节点数据</span><br><span class="line">https:<span class="comment">//learnku.com/articles/36965</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQl事务最全详解"><a href="#MySQl事务最全详解" class="headerlink" title="MySQl事务最全详解"></a>MySQl事务最全详解</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br></pre></td><td class="code"><pre><span class="line">MySQL 中的事务有如下几个特点(ACID):</span><br><span class="line"></span><br><span class="line">原子性(atomicity):</span><br><span class="line"></span><br><span class="line">一个事务必须被作为一个不可分割的最小工作单元,每个事务中的所有操作必须要么成功,或者要么失败,永远不可能一些操作失败,一些操作成功,这就是所谓的原子性的概念.</span><br><span class="line"></span><br><span class="line">一致性(consistency):</span><br><span class="line"></span><br><span class="line">一致性就像上面举的一个例子一样,当发生异常情况下,数据仍然是正确的.就是说当一个事务执行失败了,数据之间是不会受异常的情况而影响,永远保持着他的正确性.</span><br><span class="line"></span><br><span class="line">隔离性(isolation):</span><br><span class="line"></span><br><span class="line">当一个事务还未提交,每个事务之间是相互隔离的,互补受到影响.</span><br><span class="line"></span><br><span class="line">持久性(durability):</span><br><span class="line"></span><br><span class="line">当一个事务进行提交之后,发生的变化就会永远保存在数据库中.</span><br><span class="line"></span><br><span class="line">事务的隔离级别</span><br><span class="line"></span><br><span class="line">可重复读(REPEATABLE READ)</span><br><span class="line"></span><br><span class="line">多次读取记录的结果都是一致的,可重复读可以解决上面的不可重复读的情况.但是有这样一种情况,当一个事务在读取某个范围的记录时,另外一个事务在这个范围内插入了一条新的数据,当事务再次进行读取数据时,发现比第一次读取记录多了一条,这就是所谓的幻读,两次读取的结果不一致.</span><br><span class="line"></span><br><span class="line">举例:小明女朋友在查看银行卡的记录时,看见有 <span class="number">5</span> 条消费记录,此时小明正在消费,这时候消费记录里面记录了这条消费记录,当女朋友再次读取记录时,发现有 <span class="number">6</span> 条记录了.</span><br><span class="line">MySQL 中事务隐式开启的,也就是说,一个 sql 语句就是一个事务,当 sql 语句执行完毕,事务就提交了.在演示的过程中,我们显式开启  上面提到了 MySQL 中事务是隐式开启的,则代表我们每一个 sql 是自动提交的,需要关闭则需要设置 autocommit 选项</span><br><span class="line"></span><br><span class="line">show variables like <span class="string">'%autocommit%'</span>;set autocommit = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 查看当前的事务隔离级别</span></span><br><span class="line"></span><br><span class="line">mysql root@<span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>:test&gt; select @@tx_isolation;</span><br><span class="line"><span class="comment">// 连接MySQL</span></span><br><span class="line"></span><br><span class="line">$mysqli = <span class="keyword">new</span> mysqli(<span class="string">'127.0.0.1'</span>, <span class="string">'root'</span>, <span class="string">'123456'</span>, <span class="string">'test'</span>, <span class="number">3306</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 关闭事务自动提交</span></span><br><span class="line"></span><br><span class="line">$mysqli-&gt;autocommit(<span class="literal">false</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 1.开启事务</span></span><br><span class="line"></span><br><span class="line">$mysqli-&gt;begin_transaction();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 2.修改数据</span></span><br><span class="line"></span><br><span class="line">$mysqli-&gt;query(<span class="string">"update user set age=10 where id=1"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 3.查看数据</span></span><br><span class="line"></span><br><span class="line">$mysqli-&gt;query(<span class="string">"select * from user"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 4.事务回滚</span></span><br><span class="line"></span><br><span class="line">$mysqli-&gt;rollback();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 5.查看数据</span></span><br><span class="line"></span><br><span class="line">$mysqli-&gt;query(<span class="string">"select * from user"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 7.修改数据</span></span><br><span class="line"></span><br><span class="line">$mysqli-&gt;query(<span class="string">"update user set age=15 where id=1"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 8.事务提交</span></span><br><span class="line"></span><br><span class="line">$mysqli-&gt;commit();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 9.事务回滚</span></span><br><span class="line"></span><br><span class="line">$mysqli-&gt;rollback();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 10.查看数据https://learnku.com/articles/33749</span></span><br><span class="line"></span><br><span class="line">$mysqli-&gt;query(<span class="string">"select * from user"</span>);</span><br><span class="line">READ COMMITTED（提交读），大多数数据库系统的默认隔离级别，一个事务开始时，只能 “看见” 已经提交的事务所做的修改，一个事务从开始直到提交之前，所做的任何修改对其他事务都是不可见的，也叫不可重复读（nonrepeatable read），有可能出现幻读（Phantom Read），指的是当某个事务在读取某个范围内的记录时，另外一个事务又在该范围内插入了新的记录，当之前的事务再次读取该范围的记录时，会产生幻行（Phantom Row）</span><br><span class="line"></span><br><span class="line">REPEATABLE READ（可重复读），通过 InnoDB 和 XtraDB 存储引擎，是 MySQL 的默认事务隔离级别，该级别保证了在同一个事物中多次读取同样记录的结果是一致的。解决了脏读，又通过多版本并发控制 mvcc 解决了幻读。https:<span class="comment">//learnku.com/articles/32336</span></span><br><span class="line">https:<span class="comment">//www.qqdeveloper.com/2019/08/18/MySQl%E4%BA%8B%E5%8A%A1%E6%9C%80%E5%85%A8%E8%AF%A6%E8%A7%A3/</span></span><br><span class="line">read uncommitted | 读未提交</span><br><span class="line">read committed | 读已提交</span><br><span class="line">repeatable read | 可重复读</span><br><span class="line">serializable | 串行化</span><br><span class="line">事务 A 读取了事务 B 更新的数据，然后事务 B 在某些因素下执行了回滚，那么事务 A 读取的数据就是不合理的，即脏数据。</span><br><span class="line">事务 A 需要重复多次读取某组数据，事务 A 在事务 B 对该组数据修改提交前后进行读取，很显然、两次读取的数据是不一致的，即不可重复读。侧重于元数据的修改。</span><br><span class="line">事务 A 在修改每一条元数据的时候，事务 B 在此时添加了一条新记录，事务 A 在处理的过程中突然多了一条数据，即幻读。侧重于数据的删除与修改。隔离级别越高，越能保证数据的完整性和一致性，但是对并发性能的影响也越大。</span><br><span class="line">                                                                        事务隔离级别为读提交时，写数据只会锁住相应的行</span><br><span class="line">                                                                        事务隔离级别为串行化时，读写数据都会锁住整张表</span><br><span class="line">   https:<span class="comment">//learnku.com/articles/24581                                                                     </span></span><br><span class="line">    不可重复读的和幻读很容易混淆，不可重复读侧重于修改，幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行，解决幻读需要锁表 https:<span class="comment">//learnku.com/articles/30933</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL大小写不敏感问题"><a href="#MySQL大小写不敏感问题" class="headerlink" title="MySQL大小写不敏感问题"></a>MySQL大小写不敏感问题</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">show create table t3\G</span><br><span class="line">*************************** <span class="number">1.</span> row ***************************</span><br><span class="line">       Table: t3</span><br><span class="line">Create Table: CREATE TABLE <span class="string">`t3`</span> (</span><br><span class="line">  <span class="string">`a`</span> varchar(<span class="number">20</span>) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,</span><br><span class="line">  <span class="string">`b`</span> varchar(<span class="number">20</span>) DEFAULT NULL</span><br><span class="line">) ENGINE=InnoDB DEFAULT CHARSET=utf8</span><br><span class="line"><span class="number">1</span> row <span class="keyword">in</span> set (<span class="number">0.00</span> sec)</span><br><span class="line">a列有个校验规则为collate utf8_bin的设置，这个就是在a列上查询可以区分大小写的原因。 </span><br><span class="line"></span><br><span class="line">可以通过show collation命令查看有哪些校验规则：</span><br><span class="line"></span><br><span class="line">mysql&gt; show collation like <span class="string">'utf8%'</span>;</span><br><span class="line">通过show character set查看有哪些字符集：</span><br><span class="line"></span><br><span class="line">mysql&gt; show character set like <span class="string">'utf8%'</span>;</span><br><span class="line">可以看到utf8的默认校验规则是utf8general_ci，想要设置在某一列上查询区分大小写，可能通过对列指定collate utf8_bin来解决。</span><br><span class="line">https:<span class="comment">//www.daemoncoder.com/a/MySQL%E5%A4%A7%E5%B0%8F%E5%86%99%E4%B8%8D%E6%95%8F%E6%84%9F%E9%97%AE%E9%A2%98/4e413d3d</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL分页offset过大性能问题与优化"><a href="#MySQL分页offset过大性能问题与优化" class="headerlink" title="MySQL分页offset过大性能问题与优化"></a>MySQL分页offset过大性能问题与优化</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">SELECT b FROM t WHERE c&lt;<span class="number">1000</span> LIMIT <span class="number">2000000</span>, <span class="number">500</span></span><br><span class="line">可以看到这个一个分页查询，从位置<span class="number">2000000</span>处开始，取<span class="number">500</span>条数据，问题的原因正是这个过大的分页起点导致。mysql分页查询会并不是直接跳过前<span class="number">2000000</span>再取出<span class="number">500</span>条数据，而是把前<span class="number">2000000</span>条和后面的<span class="number">500</span>条都取出来，再把前<span class="number">2000000</span>条抛弃，这样的话，上面的慢查询相当于从表中取<span class="number">2000500</span>条数据，这么大的数据量必然会慢。</span><br><span class="line"></span><br><span class="line">解决方案</span><br><span class="line"></span><br><span class="line">sql修改为：</span><br><span class="line"></span><br><span class="line">SELECT b FROM (SELECT a FROM t WHERE c&lt;<span class="number">1000</span> LIMIT <span class="number">2000000</span>, <span class="number">500</span>) ta INNER JOIN t tb ON ta.a = tb.a</span><br><span class="line">这种方式先用一个子查询表的主键（还是和原来一样带有过大分页），结果做为一个临时表，再和原来的t表JOIN，查出需要的字段。</span><br><span class="line"></span><br><span class="line">这种方式不仔细看的话，也是要查出<span class="number">2000500</span>条数据，因为子任务的where和limit设置和原来一样，关键就在于子任务SELECT出来的是a字段（t表的主键），而不是像原来直接b字段，这样查出<span class="number">500</span>条数据后再和原有的表join再查出需要的数据字段b，下面详细分析下这个细节带来的性能差异。</span><br><span class="line"></span><br><span class="line">基础知识：innodb的索引分为聚集索引和辅助索引，innodb是用聚集索引组织数据的，辅助索引上只存了一个主键，按辅助索引查询数据时，先从辅助索引对应记录的主键，再用主键去聚集索引查具体的数据字段。（这里不详细分析两个种索引的区别，不了解可以自行百度）</span><br><span class="line"></span><br><span class="line">上面的慢sql会从辅助索上查<span class="number">2000500</span>条数据，对于每一条数据还要从聚集索引上查一次。修改后的sql会从辅助索引上查出<span class="number">2000500</span>条主键，由于辅助索引上本身就有主键，所以这<span class="number">2000500</span>无需再去聚集索引查，生成临时表后再把这<span class="number">500</span>条数据去聚集索引查出b字段，sql从聚集索引中查<span class="number">2000500</span>条数据变成了只需要查<span class="number">500</span>条，并且b字段在真实的情况往往是大量数据的字段，因此修改前后的sql性能差别很大（这里我理解修改前的sql按辅助索引顺序查询时，再去查聚集索引就不再是顺序读了，而是随机的离散读，也是一部分性能差的原因，具体只是自己的猜测，没有验证）。</span><br><span class="line">https:<span class="comment">//www.daemoncoder.com/a/MySQL%E5%88%86%E9%A1%B5offset%E8%BF%87%E5%A4%A7%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98%E4%B8%8E%E4%BC%98%E5%8C%96/4d513d3d</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL-反向模糊查找"><a href="#MySQL-反向模糊查找" class="headerlink" title="MySQL 反向模糊查找"></a>MySQL 反向模糊查找</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">假如数据库我们只存一条记录, 不管用户输入, 大卫还是大卫王我们都会回复它同一个内容.这时候我们只需要反向模糊查找即可</span><br><span class="line">表数据如下</span><br><span class="line">id     keyword      reply</span><br><span class="line"><span class="number">1</span>      %大卫%       他就是大卫</span><br><span class="line">select * <span class="keyword">from</span> table_name where <span class="string">'大卫'</span> like keyword</span><br><span class="line"></span><br><span class="line">http:<span class="comment">//www.shiguopeng.cn/archives/379</span></span><br></pre></td></tr></table></figure>
<h3 id="大表分页查询调研"><a href="#大表分页查询调研" class="headerlink" title="大表分页查询调研"></a>大表分页查询调研</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; explain select * <span class="keyword">from</span> user_status_record_1 order by id limit <span class="number">5000000</span>,<span class="number">5</span>;</span><br><span class="line">+----+-------------+----------------------+-------+---------------+---------+---------+------+---------+-------+</span><br><span class="line">| id | select_type | table                | type  | possible_keys | key     | key_len | ref  | rows    | Extra |</span><br><span class="line">+----+-------------+----------------------+-------+---------------+---------+---------+------+---------+-------+</span><br><span class="line">|  <span class="number">1</span> | SIMPLE      | user_status_record_1 | index | NULL          | PRIMARY | <span class="number">8</span>       | NULL | <span class="number">5000005</span> |       |</span><br><span class="line">+----+-------------+----------------------+-------+---------------+---------+---------+------+---------+-------+</span><br><span class="line"><span class="number">1</span> row <span class="keyword">in</span> set (<span class="number">0.01</span> sec)</span><br><span class="line"></span><br><span class="line">mysql&gt; explain SELECT * FROM anti_health_rate_43 WHERE id &gt;=(select id <span class="keyword">from</span> anti_health_rate_43 limit <span class="number">2000010</span>, <span class="number">1</span>) limit <span class="number">5</span>;</span><br><span class="line">+----+-------------+---------------------+-------+---------------+----------------+---------+------+---------+-------------+</span><br><span class="line">| id | select_type | table               | type  | possible_keys | key            | key_len | ref  | rows    | Extra       |</span><br><span class="line">+----+-------------+---------------------+-------+---------------+----------------+---------+------+---------+-------------+</span><br><span class="line">|  <span class="number">1</span> | PRIMARY     | anti_health_rate_43 | range | PRIMARY       | PRIMARY        | <span class="number">8</span>       | NULL | <span class="number">1779770</span> | Using where |</span><br><span class="line">|  <span class="number">2</span> | SUBQUERY    | anti_health_rate_43 | index | NULL          | idx_create_day | <span class="number">4</span>       | NULL | <span class="number">3559541</span> | Using index |</span><br><span class="line">+----+-------------+---------------------+-------+---------------+----------------+---------+------+---------+-------------+</span><br><span class="line"><span class="number">2</span> rows <span class="keyword">in</span> set (<span class="number">0.27</span> sec)</span><br><span class="line">$ret = select id <span class="keyword">from</span> table order by aaa limit <span class="number">100</span>,<span class="number">10</span></span><br><span class="line">select * <span class="keyword">from</span> table where id <span class="keyword">in</span> ( $ret );</span><br><span class="line">https:<span class="comment">//bettercuicui.github.io/2018/04/01/MYSQL/%E5%A4%A7%E8%A1%A8%E5%88%86%E9%A1%B5%E6%9F%A5%E8%AF%A2%E8%B0%83%E7%A0%94/</span></span><br></pre></td></tr></table></figure>
<h3 id="修改密码"><a href="#修改密码" class="headerlink" title="修改密码"></a>修改密码</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">先把root的旧密码置空</span><br><span class="line">use mysql;</span><br><span class="line">update user set authentication_string=<span class="string">''</span> where user=<span class="string">'root'</span>;</span><br><span class="line">备注：Mysql5<span class="number">.7</span>+ password字段 已改成 authentication_string字段</span><br><span class="line">重置成新密码</span><br><span class="line">alter user <span class="string">'root'</span>@<span class="string">'localhost'</span> identified by <span class="string">'newpassword'</span>;</span><br><span class="line">备注：Mysql8<span class="number">.0</span>修改密码方式已有变化（此处是个坑，需要注意）</span><br><span class="line">Mysql8<span class="number">.0</span>之前：</span><br><span class="line">update user set password=password(<span class="string">'root'</span>) where user=<span class="string">'root'</span>;</span><br><span class="line">mysql -uroot -proot</span><br><span class="line">https:<span class="comment">//learnku.com/articles/38466  https://learnku.com/articles/38455</span></span><br></pre></td></tr></table></figure>
<h3 id="Orderby-排序优化"><a href="#Orderby-排序优化" class="headerlink" title="Orderby 排序优化"></a>Orderby 排序优化</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">Create Table: CREATE TABLE <span class="string">`user`</span> (</span><br><span class="line"><span class="string">`id`</span> int(<span class="number">10</span>) unsigned NOT NULL AUTO_INCREMENT,</span><br><span class="line"><span class="string">`name`</span> varchar(<span class="number">20</span>) NOT NULL,</span><br><span class="line"><span class="string">`age`</span> int(<span class="number">10</span>) NOT NULL DEFAULT <span class="string">'0'</span>,</span><br><span class="line"><span class="string">`city`</span> varchar(<span class="number">20</span>) NOT NULL,</span><br><span class="line"><span class="string">`addr`</span> varchar(<span class="number">50</span>) DEFAULT NULL,</span><br><span class="line">PRIMARY KEY (<span class="string">`id`</span>),</span><br><span class="line">KEY <span class="string">`idx_name_age_city`</span> (<span class="string">`name`</span>,<span class="string">`age`</span>,<span class="string">`city`</span>)</span><br><span class="line">) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci</span><br><span class="line"></span><br><span class="line">order by 能使用索引最左前缀</span><br><span class="line">* select id,name,age,city <span class="keyword">from</span> user order by name;</span><br><span class="line">* select id,name,age,city <span class="keyword">from</span> user order by name,age,city;</span><br><span class="line">* explain select id,name,age,city <span class="keyword">from</span> user order by name desc,age desc,city desc</span><br><span class="line">如果 where 使用索引的最左前缀定义为常量，则 order by 能使用索引</span><br><span class="line">* select * <span class="keyword">from</span> user where name = <span class="string">'zhangsan'</span> order by age,city;</span><br><span class="line">* select * <span class="keyword">from</span> user where name = <span class="string">'zhangsan'</span> and age = <span class="number">20</span> order by city;</span><br><span class="line">* select * <span class="keyword">from</span> user where name = <span class="string">'zhangsan'</span> and age &gt; <span class="number">20</span> order by age,city;</span><br><span class="line"></span><br><span class="line">不能使用索引进行排序</span><br><span class="line">select * <span class="keyword">from</span> user order by name,age,city;<span class="comment">//query*字段</span></span><br><span class="line">select * <span class="keyword">from</span> user order by addr;<span class="comment">//非索引字段排序</span></span><br><span class="line">select * <span class="keyword">from</span> user order by name,addr;<span class="comment">//含有非索引字段</span></span><br><span class="line">select * <span class="keyword">from</span> user where age = <span class="number">20</span> order by city;<span class="comment">//跳过了name字段，违反最左前缀法则</span></span><br><span class="line">select * <span class="keyword">from</span> user where name = <span class="string">'zhangsan'</span> order by city;<span class="comment">//跳过了age字段，违反最左前缀法则</span></span><br><span class="line">select * <span class="keyword">from</span> user where name = <span class="string">'zhangsan'</span> order by age,addr;<span class="comment">//含有非索引字段</span></span><br><span class="line">https:<span class="comment">//learnku.com/articles/38925</span></span><br></pre></td></tr></table></figure>
<h3 id="更新同一个表不同字段"><a href="#更新同一个表不同字段" class="headerlink" title="更新同一个表不同字段"></a>更新同一个表不同字段</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">update diag_product_list_ios <span class="keyword">as</span> a join (select soft_package_id,soft_name <span class="keyword">from</span> diag_product_list_ios where pdt_code=<span class="string">'ThinkDiag'</span> ) <span class="keyword">as</span> b on a.soft_package_id=b.soft_package_id set a.soft_name=b.soft_name where a.pdt_code=<span class="string">'EASYDIAG4'</span> and a.soft_name is <span class="literal">null</span></span><br></pre></td></tr></table></figure>
<h3 id="慢查询分析调优工具"><a href="#慢查询分析调优工具" class="headerlink" title="慢查询分析调优工具"></a>慢查询分析调优工具</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">show variables like <span class="string">'profiling%'</span>;<span class="comment">//默认关闭，保存近15次的运行结果</span></span><br><span class="line">set profiling = on;</span><br><span class="line">show profiles;</span><br><span class="line">备注：</span><br><span class="line">show warnings;<span class="comment">//可以显示警告和报错的信息</span></span><br><span class="line">show profile cpu,block io <span class="keyword">for</span> query <span class="number">3</span>;</span><br><span class="line">通过Status一列，可以看到整条SQL的运行过程</span><br><span class="line">如出现以下一种或者几种情况，说明SQL执行性能极其低下，亟需优化</span><br><span class="line">* converting HEAP to MyISAM  <span class="comment">//查询结果太大，内存都不够用了往磁盘上搬了</span></span><br><span class="line">* Creating tmp table <span class="comment">//创建临时表：拷贝数据到临时表，用完再删</span></span><br><span class="line">* Copying to tmp table on disk <span class="comment">//把内存中临时表复制到磁盘，危险</span></span><br><span class="line">* locked <span class="comment">//出现死锁</span></span><br><span class="line">select * <span class="keyword">from</span> information_schema.profiling;</span><br><span class="line"></span><br><span class="line">记录sql到数据库（建议只在测试库环境进行）</span><br><span class="line"></span><br><span class="line">方式<span class="number">1</span>:命令行</span><br><span class="line"><span class="number">1.</span> set global general_log = <span class="number">1</span>;</span><br><span class="line"><span class="number">2.</span> set global log_output = <span class="string">'TABLE'</span>;</span><br><span class="line">方式<span class="number">2</span>:配置文件</span><br><span class="line">* vim my.cnf</span><br><span class="line">general_log =<span class="number">1</span></span><br><span class="line">general_log_file = <span class="regexp">/path/</span>logfile</span><br><span class="line">log_output = FILE</span><br><span class="line">* 重启MySQL服务</span><br><span class="line">诊断 SQL</span><br><span class="line">select * <span class="keyword">from</span> mysql.general_log;</span><br><span class="line">https:<span class="comment">//learnku.com/articles/39087</span></span><br></pre></td></tr></table></figure>
<h3 id="慢查询分析调优工具-1"><a href="#慢查询分析调优工具-1" class="headerlink" title="慢查询分析调优工具"></a>慢查询分析调优工具</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">show variables like <span class="string">'%slow_query_log%'</span>;</span><br><span class="line">* slow_query_log <span class="comment">//是否开启，默认关闭，建议调优时才开启</span></span><br><span class="line">* slow_query_log_file <span class="comment">//慢查询日志存放目录</span></span><br><span class="line">set global slow_query_log =<span class="number">1</span>; <span class="comment">//只对当前会话生效，重启失效</span></span><br><span class="line">show variables like <span class="string">'long_query_time%'</span>;<span class="comment">//查看阀值（大于），默认10s</span></span><br><span class="line">set global long_query_time = <span class="number">3</span> <span class="comment">//设置慢查询阀值</span></span><br><span class="line">如何把未使用索引的 SQL 记录写入慢查询日志</span><br><span class="line">show variables like <span class="string">'log_queries_not_using_indexes'</span>; <span class="comment">//查看设置，默认关闭</span></span><br><span class="line">set global log_queries_not_using_indexes = on; <span class="comment">//设置</span></span><br><span class="line">select sleep(<span class="number">4</span>);<span class="comment">//睡眠4s再执行</span></span><br><span class="line">show global status like <span class="string">'%Slow_queries%'</span>;<span class="comment">//查看慢查询条数</span></span><br><span class="line">得到返回记录集最多的<span class="number">10</span>条SQL：</span><br><span class="line">mysqldumpslow -s r -t  <span class="number">10</span> /<span class="keyword">var</span>/lib/mysql/<span class="number">695</span>f5026f0f6-slow.log</span><br><span class="line">得到访问次数最多的<span class="number">10</span>条SQL：</span><br><span class="line">mysqldumpslow -s r -t  <span class="number">10</span> /<span class="keyword">var</span>/lib/mysql/<span class="number">695</span>f5026f0f6-slow.log</span><br><span class="line">得到按照时间排序的前<span class="number">10</span>条里面含有左连接的SQL：</span><br><span class="line">mysqldumpslow -s t -t <span class="number">10</span> -g <span class="string">"left join"</span> /<span class="keyword">var</span>/lib/mysql/<span class="number">695</span>f5026f0f6-slow.log</span><br><span class="line">也支持管道符命令</span><br><span class="line">mysqldumpslow -s t -t <span class="number">10</span> -g <span class="string">"left join"</span> /<span class="keyword">var</span>/lib/mysql/<span class="number">695</span>f5026f0f6-slow.log | more <span class="comment">//分页显示</span></span><br><span class="line"></span><br><span class="line">cat /<span class="keyword">var</span>/lib/mysql/<span class="number">695</span>f5026f0f6-slow.log <span class="comment">//查看慢查询日志</span></span><br><span class="line">-- 执行SQL时间</span><br><span class="line"># Time: 2019-12-31T05:54:23.893042Z</span><br><span class="line">-- 执行SQL的主机信息</span><br><span class="line"># User@Host: root[root] @ localhost []  Id:    40</span><br><span class="line">-- SQL的执行信息</span><br><span class="line"># Query_time: 4.013664  Lock_time: 0.000000 Rows_sent: 1  Rows_examined: 1</span><br><span class="line">-- SQL执行时间</span><br><span class="line">SET timestamp=<span class="number">1577771659</span>;</span><br><span class="line">-- SQL内容</span><br><span class="line">select sleep(<span class="number">4</span>);</span><br><span class="line">https:<span class="comment">//learnku.com/articles/39009</span></span><br></pre></td></tr></table></figure>
<h3 id="索引失效"><a href="#索引失效" class="headerlink" title="索引失效"></a>索引失效</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">explain select * <span class="keyword">from</span> user where name = <span class="string">'zhangsan'</span> and age = <span class="number">20</span> and pos = <span class="string">'cxy'</span> and phone = <span class="string">'18730658760'</span>;</span><br><span class="line">如果索引有多列，要遵守最左前缀法则</span><br><span class="line">即查询从索引的最左前列开始并且不跳过索引中的列</span><br><span class="line">explain select * <span class="keyword">from</span> user where age = <span class="number">20</span> and phone = <span class="string">'18730658760'</span> and pos = <span class="string">'cxy'</span>;</span><br><span class="line">mysql在使用不等于（!=、&lt;&gt;）的时候无法使用索引会导致全表扫描（除覆盖索引外）</span><br><span class="line">explain select * <span class="keyword">from</span> user where age != <span class="number">20</span>;</span><br><span class="line">explain select * <span class="keyword">from</span> user where age &lt;&gt; <span class="number">20</span>;</span><br><span class="line">少用or</span><br><span class="line">explain select * <span class="keyword">from</span> user where name = <span class="string">'2000'</span> or age = <span class="number">20</span> or pos =<span class="string">'cxy'</span>;</span><br><span class="line">正常（索引参与了排序）</span><br><span class="line">explain select * <span class="keyword">from</span> user where name = <span class="string">'zhangsan'</span> and age = <span class="number">20</span> order by age,pos;</span><br><span class="line">备注：索引有两个作用：排序和查找</span><br><span class="line">https:<span class="comment">//learnku.com/articles/38889</span></span><br><span class="line">导致额外的文件排序（会降低性能）</span><br><span class="line">explain select name,age <span class="keyword">from</span> user where name = <span class="string">'zhangsan'</span> order by pos;<span class="comment">//违反最左前缀法则</span></span><br><span class="line">explain select name,age <span class="keyword">from</span> user where name = <span class="string">'zhangsan'</span> order by pos,age;<span class="comment">//违反最左前缀法则</span></span><br><span class="line">explain select * <span class="keyword">from</span> user where name = <span class="string">'zhangsan'</span> and age = <span class="number">20</span> order by created_time,age;<span class="comment">//含非索引字段</span></span><br></pre></td></tr></table></figure>
<h3 id="布尔值来作为-Group-By-Raw-条件"><a href="#布尔值来作为-Group-By-Raw-条件" class="headerlink" title="布尔值来作为 Group By Raw 条件"></a>布尔值来作为 Group By Raw 条件</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">如何根据「 <span class="number">2001</span> 年之前和 <span class="number">2001</span> 年之后出生」 的条件进行分组？这是代码:</span><br><span class="line"></span><br><span class="line">$results = User::select(\DB::raw(<span class="string">'YEAR(birth_date) &lt; 2001 as adult, COUNT(id) as amount'</span>))</span><br><span class="line">    -&gt;groupBy(\DB::raw(<span class="string">'YEAR(birth_date) &lt; 2001'</span>))</span><br><span class="line">    -&gt;get();</span><br><span class="line">看起来很奇怪，对吧？让我解释一下。条件年份 (出生日期)&lt;<span class="number">2001</span> 将返回两个值之一 真或假。换句话说，<span class="number">1</span> 或 <span class="number">0</span>。这正是我们需要分组的地方 —— 不管这个人是不是成年人。</span><br><span class="line">https:<span class="comment">//learnku.com/laravel/t/39537#reply126312</span></span><br></pre></td></tr></table></figure>
<h3 id="悲观锁与乐观锁"><a href="#悲观锁与乐观锁" class="headerlink" title="悲观锁与乐观锁"></a>悲观锁与乐观锁</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">CREATE TABLE <span class="string">`order_stock`</span> (</span><br><span class="line">  <span class="string">`id`</span> int(<span class="number">11</span>) NOT NULL AUTO_INCREMENT COMMENT <span class="string">'ID'</span>,</span><br><span class="line">  <span class="string">`oid`</span> int(<span class="number">50</span>) NOT NULL COMMENT <span class="string">'商品ID'</span>,</span><br><span class="line">  <span class="string">`quantity`</span> int(<span class="number">20</span>) NOT NULL COMMENT <span class="string">'库存'</span>,</span><br><span class="line">  PRIMARY KEY (<span class="string">`id`</span>)</span><br><span class="line">) ENGINE=InnoDB AUTO_INCREMENT=<span class="number">2</span> DEFAULT CHARSET=utf8;</span><br><span class="line">“乐观锁🔒”认为拿锁的用户多半是会成功的，因此在进行完业务操作需要实际更新数据的最后一步再去拿一下锁就好。这样就可以避免使用数据库自身定义的行锁，可以避免死锁现象的产生。</span><br><span class="line"></span><br><span class="line">UPDATE order_stock SET quantity = quantity - <span class="number">1</span> WHERE oid = <span class="number">1</span> AND quantity - <span class="number">1</span> &gt; <span class="number">0</span>; </span><br><span class="line">乐观并发控制多数用于数据争用不大、冲突较少的环境中，这种环境中，偶尔回滚事务的成本会低于读取数据时锁定数据的成本，因此可以获得比其他并发控制方法更高的吞吐量。</span><br><span class="line">悲观锁采用了“一锁🔒二查🔍三更新”模式，就是采用数据库中自带 select ... for update 关键字进行对当前事务添加行级锁🔒，🧵先将要操作的数据进行锁上，之后执行对应查询数据并执行更新操作。</span><br><span class="line"></span><br><span class="line">BEGIN</span><br><span class="line">SELECT quantity FROM order_stock WHERE oid = <span class="number">1</span> FOR UPDATE;</span><br><span class="line">UPDATE order_stock SET quantity = <span class="number">2</span> WHERE oid = <span class="number">1</span>; </span><br><span class="line">COMMIT;</span><br><span class="line">MySQL还有个问题是select ... for update语句执行中所有扫描过的行都会被锁上，这一点很容易造成问题。因此如果在MySQL中用悲观锁务必要确定走了索引，而不是全表扫描。</span><br><span class="line">https:<span class="comment">//www.debuginn.cn/4579.html</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL-递归查询"><a href="#MySQL-递归查询" class="headerlink" title="MySQL 递归查询"></a>MySQL 递归查询</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">create table question_type (</span><br><span class="line">  id       bigint primary key  not <span class="literal">null</span></span><br><span class="line">  comment <span class="string">'问题编号'</span>,</span><br><span class="line">  parentId bigint              not <span class="literal">null</span></span><br><span class="line">  comment <span class="string">'问题父分类编号，根节点为 0'</span>,</span><br><span class="line">  name     varchar(<span class="number">20</span>)         not <span class="literal">null</span></span><br><span class="line">  comment <span class="string">'编号名称'</span>,</span><br><span class="line">  path     varchar(<span class="number">100</span>)        not <span class="literal">null</span></span><br><span class="line">  comment <span class="string">'全路径，每级使用 , 分割'</span></span><br><span class="line">)</span><br><span class="line">  comment <span class="string">'问题编号'</span>;</span><br><span class="line">insert into question_type values (<span class="number">1</span>, <span class="number">0</span>, <span class="string">'数学'</span>, <span class="string">'0,1'</span>);</span><br><span class="line">insert into question_type values (<span class="number">2</span>, <span class="number">1</span>, <span class="string">'高等数学'</span>, <span class="string">'0,1,2'</span>);</span><br><span class="line">insert into question_type values (<span class="number">3</span>, <span class="number">1</span>, <span class="string">'线性代数'</span>, <span class="string">'0,1,3'</span>);</span><br><span class="line">insert into question_type values (<span class="number">4</span>, <span class="number">0</span>, <span class="string">'英语'</span>, <span class="string">'0,4'</span>);</span><br><span class="line">insert into question_type values (<span class="number">5</span>, <span class="number">4</span>, <span class="string">'即时翻译'</span>, <span class="string">'0,4,5'</span>);</span><br><span class="line">insert into question_type values (<span class="number">6</span>, <span class="number">4</span>, <span class="string">'口语阅读'</span>, <span class="string">'0,4,6'</span>);</span><br><span class="line">insert into question_type values (<span class="number">7</span>, <span class="number">0</span>, <span class="string">'物理'</span>, <span class="string">'0,7'</span>);</span><br><span class="line">insert into question_type values (<span class="number">8</span>, <span class="number">7</span>, <span class="string">'高能物理'</span>, <span class="string">'0,7,8'</span>);</span><br><span class="line">insert into question_type values (<span class="number">9</span>, <span class="number">8</span>, <span class="string">'无限能量'</span>, <span class="string">'0,7,8,9'</span>);</span><br><span class="line">insert into question_type values (<span class="number">10</span>, <span class="number">9</span>, <span class="string">'迪克拉之海'</span>, <span class="string">'0,7,8,9,10'</span>);</span><br><span class="line"># 查询物理分类及其子级</span><br><span class="line">select *</span><br><span class="line"><span class="keyword">from</span> question_type</span><br><span class="line">where path regexp concat(</span><br><span class="line">    <span class="string">','</span>, <span class="number">7</span>,</span><br><span class="line">    <span class="string">',|^'</span>, <span class="number">7</span>,</span><br><span class="line">    <span class="string">',|,'</span>, <span class="number">7</span>,</span><br><span class="line">    <span class="string">'$|^'</span>, <span class="number">7</span>,</span><br><span class="line">    <span class="string">'$'</span>);</span><br><span class="line">https:<span class="comment">//blog.rxliuli.com/p/5830226b/</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL-行列转换"><a href="#MySQL-行列转换" class="headerlink" title="MySQL 行列转换"></a>MySQL 行列转换</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line">drop table <span class="keyword">if</span> exists exam;</span><br><span class="line">create table exam (</span><br><span class="line">  name    varchar(<span class="number">20</span>) not <span class="literal">null</span></span><br><span class="line">  comment <span class="string">'姓名'</span>,</span><br><span class="line">  subject varchar(<span class="number">20</span>) not <span class="literal">null</span></span><br><span class="line">  comment <span class="string">'考试科目'</span>,</span><br><span class="line">  score   int         <span class="literal">null</span></span><br><span class="line">  comment <span class="string">'考试成绩'</span></span><br><span class="line">)</span><br><span class="line">  comment <span class="string">'考试记录'</span>;</span><br><span class="line"></span><br><span class="line">insert into exam values (<span class="string">'琉璃'</span>, <span class="string">'语文'</span>, <span class="number">90</span>);</span><br><span class="line">insert into exam values (<span class="string">'琉璃'</span>, <span class="string">'英语'</span>, <span class="number">85</span>);</span><br><span class="line">insert into exam values (<span class="string">'楚轩'</span>, <span class="string">'数学'</span>, <span class="number">100</span>);</span><br><span class="line">insert into exam values (<span class="string">'楚轩'</span>, <span class="string">'物理'</span>, <span class="number">100</span>);</span><br><span class="line">insert into exam values (<span class="string">'张三'</span>, <span class="string">'化学'</span>, <span class="number">40</span>);</span><br><span class="line">insert into exam values (<span class="string">'李四'</span>, <span class="string">'生物'</span>, <span class="number">100</span>);</span><br><span class="line">select</span><br><span class="line">  name                              <span class="keyword">as</span> <span class="string">'姓名'</span>,</span><br><span class="line">  max(<span class="keyword">if</span>(subject = <span class="string">'语文'</span>, score, <span class="number">0</span>)) <span class="keyword">as</span> <span class="string">'语文'</span>,</span><br><span class="line">  max(<span class="keyword">if</span>(subject = <span class="string">'数学'</span>, score, <span class="number">0</span>)) <span class="keyword">as</span> <span class="string">'数学'</span>,</span><br><span class="line">  max(<span class="keyword">if</span>(subject = <span class="string">'英语'</span>, score, <span class="number">0</span>)) <span class="keyword">as</span> <span class="string">'英语'</span>,</span><br><span class="line">  max(<span class="keyword">if</span>(subject = <span class="string">'物理'</span>, score, <span class="number">0</span>)) <span class="keyword">as</span> <span class="string">'物理'</span>,</span><br><span class="line">  max(<span class="keyword">if</span>(subject = <span class="string">'化学'</span>, score, <span class="number">0</span>)) <span class="keyword">as</span> <span class="string">'化学'</span>,</span><br><span class="line">  max(<span class="keyword">if</span>(subject = <span class="string">'生物'</span>, score, <span class="number">0</span>)) <span class="keyword">as</span> <span class="string">'生物'</span></span><br><span class="line"><span class="keyword">from</span> exam</span><br><span class="line">group by name;</span><br><span class="line">select</span><br><span class="line">  name                                                                  <span class="keyword">as</span> <span class="string">'姓名'</span>,</span><br><span class="line">  sum(<span class="keyword">if</span>(subject = <span class="string">'语文'</span> or subject = <span class="string">'数学'</span> or subject = <span class="string">'英语'</span>, score, <span class="number">0</span>)) <span class="keyword">as</span> <span class="string">'主科'</span>,</span><br><span class="line">  sum(<span class="keyword">if</span>(subject = <span class="string">'物理'</span> or subject = <span class="string">'化学'</span> or subject = <span class="string">'生物'</span>, score, <span class="number">0</span>)) <span class="keyword">as</span> <span class="string">'副科'</span></span><br><span class="line"><span class="keyword">from</span> exam</span><br><span class="line">group by name;</span><br><span class="line">select</span><br><span class="line">  name <span class="keyword">as</span> <span class="string">'姓名'</span>,</span><br><span class="line">  max(<span class="keyword">case</span> subject when <span class="string">'语文'</span> then score <span class="keyword">else</span> <span class="number">0</span> end) <span class="keyword">as</span> <span class="string">'语文'</span>,</span><br><span class="line">  max(<span class="keyword">case</span> subject when <span class="string">'数学'</span> then score <span class="keyword">else</span> <span class="number">0</span> end) <span class="keyword">as</span> <span class="string">'数学'</span>,</span><br><span class="line">  max(<span class="keyword">case</span> subject when <span class="string">'英语'</span> then score <span class="keyword">else</span> <span class="number">0</span> end) <span class="keyword">as</span> <span class="string">'英语'</span>,</span><br><span class="line">  max(<span class="keyword">case</span> subject when <span class="string">'物理'</span> then score <span class="keyword">else</span> <span class="number">0</span> end) <span class="keyword">as</span> <span class="string">'物理'</span>,</span><br><span class="line">  max(<span class="keyword">case</span> subject when <span class="string">'化学'</span> then score <span class="keyword">else</span> <span class="number">0</span> end) <span class="keyword">as</span> <span class="string">'化学'</span>,</span><br><span class="line">  max(<span class="keyword">case</span> subject when <span class="string">'生物'</span> then score <span class="keyword">else</span> <span class="number">0</span> end) <span class="keyword">as</span> <span class="string">'生物'</span></span><br><span class="line"><span class="keyword">from</span> exam</span><br><span class="line">group by name;</span><br><span class="line">https:<span class="comment">//blog.rxliuli.com/p/73dac442/</span></span><br></pre></td></tr></table></figure>
<h3 id="MySQL-获取随机条数据"><a href="#MySQL-获取随机条数据" class="headerlink" title="MySQL 获取随机条数据"></a>MySQL 获取随机条数据</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line">create table topic (</span><br><span class="line">  id      int primary key not <span class="literal">null</span></span><br><span class="line">  comment <span class="string">'编号'</span>,</span><br><span class="line">  content varchar(<span class="number">20</span>)     not <span class="literal">null</span></span><br><span class="line">  comment <span class="string">'内容'</span></span><br><span class="line">)</span><br><span class="line">  comment <span class="string">'主题表'</span>;</span><br><span class="line">select *</span><br><span class="line"><span class="keyword">from</span> topic</span><br><span class="line">order by rand()</span><br><span class="line">limit <span class="number">50000</span>;</span><br><span class="line">select *</span><br><span class="line"><span class="keyword">from</span> (</span><br><span class="line">       select</span><br><span class="line">         topic.*,</span><br><span class="line">         rand() <span class="keyword">as</span> order_column</span><br><span class="line">       <span class="keyword">from</span> topic</span><br><span class="line">     ) <span class="keyword">as</span> temp</span><br><span class="line">order by order_column</span><br><span class="line">limit <span class="number">50000</span>;</span><br><span class="line"></span><br><span class="line">select *</span><br><span class="line"><span class="keyword">from</span> topic</span><br><span class="line">where id &gt;= ((select max(id)</span><br><span class="line">              <span class="keyword">from</span> topic)</span><br><span class="line">             - (select min(id)</span><br><span class="line">                <span class="keyword">from</span> topic))</span><br><span class="line">            * rand()</span><br><span class="line">            + (select min(id)</span><br><span class="line">               <span class="keyword">from</span> topic)</span><br><span class="line">limit <span class="number">50000</span>;</span><br><span class="line">SELECT t.*</span><br><span class="line">FROM topic t</span><br><span class="line">  JOIN</span><br><span class="line">  (SELECT id</span><br><span class="line">   FROM <span class="string">`topic`</span></span><br><span class="line">   ORDER BY RAND()</span><br><span class="line">   LIMIT <span class="number">50000</span>) AS z ON z.id = t.id;</span><br><span class="line">https:<span class="comment">//blog.rxliuli.com/p/931be19d/</span></span><br></pre></td></tr></table></figure>
<p><a href="https://www.debuginn.cn/4951.html" target="_blank" rel="noopener">Redis 知识点汇总</a></p>
<p><a href="https://learnku.com/articles/38615" target="_blank" rel="noopener">一张图搞定七种 JOIN 关系</a></p>
<p><a href="https://ops-coffee.cn/s/p5UKuh1yY3P4zrOzVBmY1w" target="_blank" rel="noopener">MySQL EXPLAIN结果集分析</a></p>
<p><a href="https://anemone.top/sqli-SQL%E6%B3%A8%E5%85%A5%E6%80%BB%E7%BB%93/" target="_blank" rel="noopener">SQL注入总结</a></p>
<p><a href="https://bettercuicui.github.io/2018/04/01/MYSQL/%E6%95%B0%E6%8D%AE%E5%BA%93%E6%B0%B4%E5%B9%B3%E5%88%87%E5%88%86%E4%BA%8C%E4%B8%89%E4%BA%8B/" target="_blank" rel="noopener"> 数据库水平切分二三事</a></p>
<p><a href="https://bettercuicui.github.io/public/image/mysql/%E7%AC%AC6%E7%AB%A0%20%E9%94%81.png" target="_blank" rel="noopener">mysql锁</a></p>
<p><a href="https://bettercuicui.github.io/2018/04/01/MYSQL/InnoDB%E9%94%81/" target="_blank" rel="noopener">InnoDB锁</a></p>
<p><a href="https://learnku.com/articles/37013" target="_blank" rel="noopener">MySQL 优化笔记</a></p>
<p><a href="https://learnku.com/articles/35589" target="_blank" rel="noopener">手把手带你探索 MySQL 事务的隔离</a></p>
<p><a href="https://www.qqdeveloper.com/2019/08/18/MySQl%E4%BA%8B%E5%8A%A1%E6%9C%80%E5%85%A8%E8%AF%A6%E8%A7%A3/" target="_blank" rel="noopener">MySQl事务最全详解</a></p>
<p><a href="https://blog.ouyangsihai.cn/mysql-de-you-yi-shen-qi-suo.html" target="_blank" rel="noopener">MySQL的又一神器-锁，MySQL面试必备</a></p>
<p><a href="https://learnku.com/articles/37013" target="_blank" rel="noopener">MySQL 优化笔记</a></p>
<p><a href="https://learnku.com/articles/37040" target="_blank" rel="noopener">一条 SQL 查询语句是如何执行的</a></p>
<p><a href="https://learnku.com/articles/36523" target="_blank" rel="noopener">MySQL 表结构生成 Markdown 文档</a></p>
<p><a href="https://learnku.com/mysql/wikis/36434" target="_blank" rel="noopener">mysql wiki</a></p>
<p><a href="https://learnku.com/articles/35660" target="_blank" rel="noopener">MySQL 三大范式</a></p>
<p><a href="https://www.liaoxuefeng.com/wiki/1177760294764384/1179611432985088" target="_blank" rel="noopener">在线sql</a></p>
<p><a href="https://learnku.com/articles/35576" target="_blank" rel="noopener">事务知识点总结</a></p>
<p><a href="https://gleehub.com/program/mysql-xue-xi-bi-ji.html" target="_blank" rel="noopener">MySQL 学习笔记</a></p>
<p><a href="http://jeff-tan.github.io/2017/10/02/%E6%82%B2%E8%A7%82%E9%94%81%20&amp;%20%E4%B9%90%E8%A7%82%E9%94%81/" target="_blank" rel="noopener">悲观锁 &amp; 乐观锁</a></p>
<p>SQL注入总结<a href="https://anemone.top/sqli-SQL%E6%B3%A8%E5%85%A5%E6%80%BB%E7%BB%93/" target="_blank" rel="noopener">https://anemone.top/sqli-SQL%E6%B3%A8%E5%85%A5%E6%80%BB%E7%BB%93/</a></p>
<p><a href="https://mp.weixin.qq.com/s?__biz=MzI4NzE2MDI5NA==&amp;mid=2650280758&amp;idx=1&amp;sn=45f0c238ee6a96ca62030e095ee5a676&amp;chksm=f3dd51bfc4aad8a9cc1d6e8aca838bb742b6c9b7f2b4934bc8a1eeac0097f23aca63aaa752f4&amp;mpshare=1&amp;scene=1&amp;srcid=&amp;sharer_sharetime=1569765640739&amp;sharer_shareid=c981482699a0ec1b5f7736eac15aa25b&amp;key=20f7b87cb3d4d9a8da53f19bdd8f499d09bec0eec75803772a28388c07935ed05887351ee092ae7a2c40e6bf402ea0e6a4a7ae2c1653d765c07a65ebc1840fac7836282b04b6d6c05f46b87114387106&amp;ascene=1&amp;uin=NjQ3OTQwMTAy&amp;devicetype=Windows+7&amp;version=62070141&amp;lang=zh_CN&amp;pass_ticket=YLoS2PNn8p2iY1DXdpvym0%2Fkx1J0GU6uiBZYmtIEnqkwLW%2FGgzQoq5f%2BqsMWHZPw" target="_blank" rel="noopener">MySQL事务最全详解</a> </p>
<p><a href="https://mp.weixin.qq.com/s?__biz=MzU2NzkxMDUyNg==&amp;mid=2247484920&amp;idx=1&amp;sn=72a78473bcf1105fa107ebe2a71e0855&amp;chksm=fc974ce9cbe0c5fffb63e6e0186dba2d8dbf4113e677f23da2a10f401da8ffb1b4ad308090d8&amp;mpshare=1&amp;scene=1&amp;srcid=&amp;sharer_sharetime=1569734986919&amp;sharer_shareid=08dc8069c5231ca71a4c24702a482f37&amp;key=f8a21a8df9909cbbff14737567cfc7b5d7782dd5b837184b9322d11bd7915c579145bd4a27a5754c159f1022864d797492413f831d496402eb8eb247fa61dd367e1db198eec652623322529d774ee999&amp;ascene=1&amp;uin=NjQ3OTQwMTAy&amp;devicetype=Windows+7&amp;version=62070141&amp;lang=zh_CN&amp;pass_ticket=YLoS2PNn8p2iY1DXdpvym0%2Fkx1J0GU6uiBZYmtIEnqkwLW%2FGgzQoq5f%2BqsMWHZPw" target="_blank" rel="noopener">SQL注入的几种类型和原理</a> </p>
<p>信息收集思路整理<a href="https://anemone.top/%E4%BF%A1%E6%81%AF%E6%94%B6%E9%9B%86-%E4%BF%A1%E6%81%AF%E6%94%B6%E9%9B%86%E6%80%9D%E8%B7%AF%E6%95%B4%E7%90%86/" target="_blank" rel="noopener">https://anemone.top/%E4%BF%A1%E6%81%AF%E6%94%B6%E9%9B%86-%E4%BF%A1%E6%81%AF%E6%94%B6%E9%9B%86%E6%80%9D%E8%B7%AF%E6%95%B4%E7%90%86/</a></p>
<p><a href="https://learnku.com/articles/31832" target="_blank" rel="noopener">搭建 MySQL 主从服务器</a></p>
<p><a href="http://yyeer.com/%E6%95%B0%E6%8D%AE%E5%BA%93/2018/12/22/%E5%88%86%E5%BA%93%E5%88%86%E8%A1%A8de%E9%82%A3%E4%BA%9B%E4%BA%8B-%E7%90%86%E8%AE%BA%E7%AF%87/" target="_blank" rel="noopener">分库分表de那些事【理论篇】</a></p>
<p><a href="https://learnku.com/articles/34878" target="_blank" rel="noopener">一次慢查询优化过程</a></p>
<p><a href="https://laucyun.com/a8b422bc6a7712a001117708fc2578b3.html" target="_blank" rel="noopener">Navicat Premium 12 for Mac无补丁无毒的激活方法</a></p>
<p><a href="http://www.querymongo.com/" target="_blank" rel="noopener">一个 sql 转 mongo query 的小工具,  https://github.com/guxingke/sql2mongo </a></p>
<p><a href="https://blog.fazero.me/2017/09/15/mysql-master-slave/" target="_blank" rel="noopener">Mysql数据库设置主从同步</a></p>
<p><a href="https://learnku.com/articles/33749" target="_blank" rel="noopener">MySQL 事务最全详解</a></p>
<p><a href="https://learnku.com/articles/28609" target="_blank" rel="noopener">MySQL 索引 +explain</a></p>
<p><a href="https://learnku.com/articles/33779" target="_blank" rel="noopener">MySQL 运行原理【事务】</a></p>
<p><a href="https://learnku.com/articles/33780" target="_blank" rel="noopener">MySQL 运行原理【表】</a></p>
<p><a href="https://learnku.com/articles/25148" target="_blank" rel="noopener">MySQL 社区规范 | 数据库篇</a></p>
<p><a href="https://alpha2016.github.io/2019/04/15/MySQL%E5%8F%8D%E5%BA%94%E6%85%A2%E7%9A%84%E6%8E%92%E6%9F%A5%E6%80%9D%E8%B7%AF/" target="_blank" rel="noopener">MySQL反应慢的排查思路</a></p>
<p><a href="http://imysql.com/my-cnf-wizard.html" target="_blank" rel="noopener">my.cnf生成工具</a></p>
<p><a href="https://juejin.im/post/5d42f48cf265da03ab422e08" target="_blank" rel="noopener">后端程序员必备：mysql数据库相关流程图/原理图</a></p>
<p><a href="https://mengkang.net/1328.html" target="_blank" rel="noopener">Mysql 使用 optimizer_trace 查看执行流程，分析、验证优化思路</a></p>
<p><a href="https://mengkang.net/1355.html" target="_blank" rel="noopener">一次 group by + order by 性能优化分析</a></p>
<p><a href="https://learnku.com/articles/30486" target="_blank" rel="noopener">sql_mode=only_full_group_by 错误</a></p>
<p> <a href="https://www.cnblogs.com/glon/p/6761028.html" target="_blank" rel="noopener">ClickHouse 快速入门</a></p>
<p><a href="http://mywebsql.net/" target="_blank" rel="noopener">在线执行sql </a></p>
<p><a href="https://github.com/danfengcao/binlog2sql" target="_blank" rel="noopener">MySQL数据恢复工具binlog2sql</a></p>
<p><a href="https://www.restran.net/2018/10/29/ctf-sqli-notes/" target="_blank" rel="noopener">CTF 中的 SQL 注入总结</a></p>
<p><a href="https://blog.smoker.cc/mysql/common-skills.html" target="_blank" rel="noopener">MySQL 常用技巧</a></p>
<p><a href="https://segmentfault.com/p/1210000008951080/read" target="_blank" rel="noopener">mysql 证明为什么用limit时，offset很大会影响性能</a></p>
<p><a href="https://learnku.com/articles/26067" target="_blank" rel="noopener">MySQL 细致总结之基础篇</a></p>
<p><a href="https://www.v2ex.com/t/472180" target="_blank" rel="noopener">mysql connection time out</a></p>
<p><a href="https://blog.xupeng.me/2013/10/11/mysql-replace-into-trap/" target="_blank" rel="noopener">mysql replace into 坑</a></p>
<p><a href="https://mp.weixin.qq.com/s/CMYHiW3hgDCBYH5P1XcmaQ" target="_blank" rel="noopener">Redis学习</a></p>
<p><a href="https://blog.yiranzai.cn/posts/990/" target="_blank" rel="noopener">MyCAT实现MySQL读写分离</a></p>
<p><a href="https://github.com/xaecbd/RCT" target="_blank" rel="noopener">Redis 内存分析工具</a></p>
<p><a href="http://eienao.com/posts/mysql-innodb-row-level-locking-mechanism.html" target="_blank" rel="noopener">mysql —— InnoDB行级锁机制</a></p>
<p><a href="https://learnku.com/articles/25148#topnav" target="_blank" rel="noopener">MySQL 社区规范 | 数据库篇</a></p>
<p><a href="https://learnku.com/articles/25116#topnav" target="_blank" rel="noopener">MySQL 规范 (数据库表设计规范)</a></p>
<p><a href="https://learnku.com/articles/25020#topnav" target="_blank" rel="noopener">MySQL 规范</a></p>
<p><a href="http://fanqieto.top/2017/11/23/mysql%E6%95%B0%E6%8D%AE%E5%BA%93%E7%BB%93%E6%9E%84%E4%BC%98%E5%8C%96/" target="_blank" rel="noopener">mysql数据库结构优化</a></p>
<p><a href="https://mp.weixin.qq.com/s/OzAnRVPUDtoiIXqeC7YL6g" target="_blank" rel="noopener">阿里云Redis开发规范</a></p>
<p><a href="https://mp.weixin.qq.com/s/F0PrHNqfD-JVn8if3q8S0Q" target="_blank" rel="noopener">MySQL索引优化实战</a></p>
<p><a href="https://mp.weixin.qq.com/s/EC5cgQ1ne9ZR0jFvznHBfg" target="_blank" rel="noopener">一个字节的网络漫游故事独白</a></p>
<p><a href="https://mp.weixin.qq.com/mp/homepage?__biz=MzI0MDQ4MTM5NQ==&amp;hid=8&amp;sn=1db566bed001a8db6d9927540ccc2156&amp;scene=1&amp;devicetype=iOS12.1.2&amp;version=17000326&amp;lang=zh_CN&amp;nettype=WIFI&amp;ascene=7&amp;session_us=gh_53f281f2ae80&amp;fontScale=100&amp;wx_header=1" target="_blank" rel="noopener">技术精选</a></p>
<p><a href="https://mp.weixin.qq.com/s/FIMDOksAej5uqxT1YksyxA" target="_blank" rel="noopener">Redis过期策略及实现原理</a></p>
<p><a href="https://mp.weixin.qq.com/s/Z3Juad9pz33EWiKAH7ZgzA" target="_blank" rel="noopener">19条MySQL优化</a></p>
<p><a href="https://www.cnblogs.com/junwangzhe/p/6420049.html" target="_blank" rel="noopener">Mysql分表和分区的区别、分库分表介绍与区别</a></p>
<p><a href="https://www.cnblogs.com/it-cen/p/4984272.html" target="_blank" rel="noopener">用Redis实现分布式锁 与 实现任务队列</a></p>
<p><a href="https://segmentfault.com/a/1190000016902003" target="_blank" rel="noopener">面试官问你如何解决web高并发这样回答就好了</a></p>
<p><a href="https://www.cnblogs.com/it-cen/p/4984272.html" target="_blank" rel="noopener">Redis实现分布式锁与任务队列的思路与源码 </a></p>
<p><a href="https://www.cnblogs.com/-mrl/p/9519259.html" target="_blank" rel="noopener">PHP+Redis，实现延迟任务 实现自动取消订单，自动完成订</a></p>
<p><a href="https://www.v2ex.com/t/536138#reply149" target="_blank" rel="noopener">MySQL 图形化工具 </a></p>
<p><a href="https://mp.weixin.qq.com/s/PbtikNJlGmsR2iLSIA4aMw" target="_blank" rel="noopener">MYSQL的SQL性能优化总结</a></p>
<p><a href="https://www.einsition.com/article/14/details" target="_blank" rel="noopener">MySQL 主从复制 实例讲解</a></p>
<p><a href="https://juejin.im/post/5a912b3f5188257a5c608729" target="_blank" rel="noopener">Redis从入门到实践</a></p>
<p><a href="https://github.com/jaywcjlove/handbook/tree/master/Redis" target="_blank" rel="noopener">10分钟快速入门Redis</a></p>
<p><a href="http://cenalulu.github.io/mysql/mysql-tools-list/" target="_blank" rel="noopener">MySQL工具汇总</a></p>
<p><a href="http://www.54php.cn/default/240.html" target="_blank" rel="noopener">MySQL 大表优化方案</a></p>
<p><a href="http://www.syyong.com/db/Mysql-lock.html" target="_blank" rel="noopener">Mysql 锁</a></p>
<p><a href="https://www.0php.net/posts/%E5%A4%87%E5%BF%98-PHP-PDO-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86.html" target="_blank" rel="noopener">pdo bindParam bindValue</a></p>
<p><a href="https://www.0php.net/posts/MySQL-%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E5%AE%9E%E9%AA%8C-%E8%AE%A4%E8%AF%86%EF%BC%9A%E8%84%8F%E8%AF%BB%E3%80%81%E4%B8%8D%E5%8F%AF%E9%87%8D%E5%A4%8D%E8%AF%BB%E3%80%81%E5%B9%BB%E8%AF%BB.html" target="_blank" rel="noopener">MYSQL 事务隔离实验-认识：脏读、不可重复读、幻读</a></p>
<p><a href="http://seanlook.com/2018/03/21/mysql-pagination-no-offset/" target="_blank" rel="noopener">MySQL分页优化</a></p>
<p><a href="https://www.awaimai.com/1910.html" target="_blank" rel="noopener">msyql日志</a></p>
<p><a href="http://mysql.taobao.org/monthly/2017/11/09/" target="_blank" rel="noopener">MySQL · 最佳实践 · 分区表基本类型</a></p>
<p><a href="https://laravel-china.org/topics/17508" target="_blank" rel="noopener">花式搭建 Laravel 运行环境</a></p>
<p><a href="http://www.helpergarden.com/2018/05/mysql%e4%b8%ad%e7%9a%84%e6%95%b0%e6%8d%ae%e5%ad%98%e5%82%a8%e9%80%89%e6%8b%a9.html" target="_blank" rel="noopener">mysql中的数据存储选择</a></p>
<p><a href="https://www.fanhaobai.com/2016/05/lnmp.html" target="_blank" rel="noopener">安装LNMP开发环境</a></p>
<p><a href="http://www.helpergarden.com/2014/03/mysql-masterslave-%e5%ae%9e%e6%88%98.html" target="_blank" rel="noopener">Mysql Master&amp;Slave 实战</a></p>
<p><a href="https://www.raymondwu.net/2018/07/26/Laravel%E8%AF%BB%E5%86%99%E5%88%86%E7%A6%BB%E4%B8%8EMySQL%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6/" target="_blank" rel="noopener">MySQL 主从复制部署与 Laravel 读写分离配置</a></p>
<p><a href="https://laravel-china.org/articles/22190" target="_blank" rel="noopener">教你 MySQL Binlog 实用攻略</a></p>
<p><a href="https://www.goozp.com/article/22.html" target="_blank" rel="noopener">《高性能MySQL》学习笔记1——MySQL架构</a></p>
<p><a href="https://laravel-china.org/articles/22188" target="_blank" rel="noopener">MySQL 部分整理</a></p>
<p><a href="https://www.goozp.com/article/30.html" target="_blank" rel="noopener">PHP开发之网站安全</a></p>
<p><a href="https://www.woann.cn/article/10" target="_blank" rel="noopener">mysql的水平分库分表和垂直分库分表</a></p>
<p><a href="https://laravel-china.org/articles/19472#b808e0" target="_blank" rel="noopener">MySQL 索引初探</a></p>
<p><a href="https://blog.csdn.net/iechenyb/article/details/79828413" target="_blank" rel="noopener">redis主从库读写分离</a></p>
<p><a href="https://laravel-china.org/articles/13849/understanding-four-isolation-levels-in-mysql" target="_blank" rel="noopener">MySQL 中的四种隔离级别</a></p>
<p><a href="https://www.raymondwu.net/2018/07/26/Laravel%E8%AF%BB%E5%86%99%E5%88%86%E7%A6%BB%E4%B8%8EMySQL%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6/" target="_blank" rel="noopener">MySQL 主从复制部署与 Laravel 读写分离配置</a></p>
<p><a href="http://youngyu.net/post/bslaravel4" target="_blank" rel="noopener">部署Laravel实战：Step 4 MySQL主从复制</a></p>
<p><a href="https://laravel-china.org/articles/22363" target="_blank" rel="noopener">Redis 面试内容</a></p>
<p><a href="https://github.com/Qihoo360/pika/blob/master/README_CN.md" target="_blank" rel="noopener">Pika是一个可持久化的大容量redis存储服务</a></p>
<p><a href="https://laravel-china.org/articles/10735/yum-quickly-build-lnmp-development-environment" target="_blank" rel="noopener">yum 快速搭建 lnmp 开发环境</a></p>
<p><a href="https://segmentfault.com/a/1190000012164089" target="_blank" rel="noopener">redis笔记</a></p>
<p><a href="https://learnku.com/articles/22363#413d78" target="_blank" rel="noopener">面试前必须要知道的 Redis 面试内容</a></p>
<p><a href="https://zhuanlan.zhihu.com/p/36337666" target="_blank" rel="noopener">elastic stack来分析下你的redis slowlog</a></p>
<p><a href="http://www.thpffcj.com/2017/12/20/Redis-Getting-Started-2/" target="_blank" rel="noopener">Redis 入门</a></p>
<p><a href="https://www.liaoxuefeng.com/wiki/1177760294764384" target="_blank" rel="noopener">在线sqlhttp://mywebsql.net/</a></p>
<p><a href="https://learnku.com/articles/25739" target="_blank" rel="noopener">MySQL 详细学习笔记</a></p>
<p><a href="https://learnku.com/php/t/33573" target="_blank" rel="noopener">SQL 最近位置查询语句</a></p>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/mysql/" rel="tag"># mysql</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2019/01/07/代码段收集/" rel="next" title="代码段收集">
                <i class="fa fa-chevron-left"></i> 代码段收集
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2019/01/08/laravel-cache-facade/" rel="prev" title="laravel cache facade">
                laravel cache facade <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  
          <div class="comments" id="comments">
             <div id="gitment-container"></div>
         </div>
  




        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope="" itemtype="http://schema.org/Person">
            
              <p class="site-author-name" itemprop="name">苏生不惑</p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">382</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/tags/index.html">
                  <span class="site-state-item-count">37</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          

          
            <div class="links-of-author motion-element">
                
                  <span class="links-of-author-item">
                    <a href="https://github.com/sushengbuhuo" target="_blank" title="GitHub">
                      
                        <i class="fa fa-fw fa-github"></i>GitHub</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="mysusheng@gmail.com" target="_blank" title="E-Mail">
                      
                        <i class="fa fa-fw fa-envelope"></i>E-Mail</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="https://plus.google.com/mysusheng" target="_blank" title="Google">
                      
                        <i class="fa fa-fw fa-google"></i>Google</a>
                  </span>
                
            </div>
          

          
          

          
          
            <div class="links-of-blogroll motion-element links-of-blogroll-block">
              <div class="links-of-blogroll-title">
                <i class="fa  fa-fw fa-link"></i>
                Links
              </div>
              <ul class="links-of-blogroll-list">
                
                  <li class="links-of-blogroll-item">
                    <a href="http://v2ex.com/" title="v2ex" target="_blank">v2ex</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.fanhaobai.com/" title="fanhaobai" target="_blank">fanhaobai</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://yuanxuxu.com/archives/" title="yuanxuxu" target="_blank">yuanxuxu</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.snail-c.cn/article" title="snail-c" target="_blank">snail-c</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="http://showcj.com/archives" title="showcj" target="_blank">showcj</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="http://vultr.aicnm.com/%E6%9C%80%E6%96%B0Vultr%E6%B3%A8%E5%86%8C%E5%8F%8AVPS%E8%B4%AD%E4%B9%B0%E5%9B%BE%E6%96%87%E6%95%99%E7%A8%8B/" title="vultr" target="_blank">vultr</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.lucissfer.com/" title="lucissfer" target="_blank">lucissfer</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://blog.csdn.net/fdipzone/article/details/79352685" title="傲雪星枫" target="_blank">傲雪星枫</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.yoby123.cn/index.php/category/default/" title="小白的分享" target="_blank">小白的分享</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.cnblogs.com/52fhy/p/5819995.html" title="PHP攻城狮" target="_blank">PHP攻城狮</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://blog.jiaojie.site/" title="php" target="_blank">php</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://sphard.com/archives/" title="sphard" target="_blank">sphard</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://yuanxuxu.com/archives/" title="LNMP技术栈笔记" target="_blank">LNMP技术栈笔记</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="http://www.coding10.com/" title="学习 Laravel" target="_blank">学习 Laravel</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://shuwoom.com/?page_id=929" title="区块链学习指南" target="_blank">区块链学习指南</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://greenlightt.github.io/archives/" title="greenlightt" target="_blank">greenlightt</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.0php.net/archives/" title="0php" target="_blank">0php</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="http://www.fordba.com/category/mysql" title="mysql" target="_blank">mysql</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.itcodemonkey.com/" title="程序员" target="_blank">程序员</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.yanshuo.me/r/v2ex" title="言说" target="_blank">言说</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.timiguo.com/archive.html" title="提米果的博客" target="_blank">提米果的博客</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://phpartisan.cn/news/112.html" title="phpartisan" target="_blank">phpartisan</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.cnblogs.com/52fhy/" title="飞鸿影" target="_blank">飞鸿影</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="http://www.54php.cn/" title="54php" target="_blank">54php</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.lazyman.vip/" title="营销" target="_blank">营销</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.njphper.com/archives/" title="做人呢最重要的就是开心" target="_blank">做人呢最重要的就是开心</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.h57.pw/" title="php 初心者" target="_blank">php 初心者</a>
                  </li>
                
              </ul>
            </div>
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#Mysql使用别名多表查询join时问题"><span class="nav-number">1.</span> <span class="nav-text">Mysql使用别名多表查询join时问题</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#重置root密码"><span class="nav-number">2.</span> <span class="nav-text">重置root密码</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#mysql5-7无法远程连接问题"><span class="nav-number">3.</span> <span class="nav-text">mysql5.7无法远程连接问题</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#select-导致的mysql线程sending-data"><span class="nav-number">4.</span> <span class="nav-text">select *导致的mysql线程sending data</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#lumen数据库时区设置"><span class="nav-number">5.</span> <span class="nav-text">lumen数据库时区设置</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#nginx跨域设置"><span class="nav-number">6.</span> <span class="nav-text">nginx跨域设置</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#swoole-process父子进程使用队列通信"><span class="nav-number">7.</span> <span class="nav-text">swoole process父子进程使用队列通信</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#yum安装elasticsearch"><span class="nav-number">8.</span> <span class="nav-text">yum安装elasticsearch</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#grant"><span class="nav-number">9.</span> <span class="nav-text">grant</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#EXPLAIN-查看SQL执行计划"><span class="nav-number">10.</span> <span class="nav-text">EXPLAIN 查看SQL执行计划</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#卸载mysql8"><span class="nav-number">11.</span> <span class="nav-text">卸载mysql8</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#安装mysql5-7"><span class="nav-number">12.</span> <span class="nav-text">安装mysql5.7</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#查看实时执行的SQL语句"><span class="nav-number">13.</span> <span class="nav-text">查看实时执行的SQL语句</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Can’t-connect-to-local-MySQL-server"><span class="nav-number">14.</span> <span class="nav-text">Can’t connect to local MySQL server</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Access-denied-for-user-‘root‘-’localhost’"><span class="nav-number">15.</span> <span class="nav-text">Access denied for user ‘root‘@’localhost’</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Can’t-connect-to-MySQL-server-on-‘127-0-0-1’"><span class="nav-number">16.</span> <span class="nav-text">Can’t connect to MySQL server on ‘127.0.0.1’</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#转换编码"><span class="nav-number">17.</span> <span class="nav-text">转换编码</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#安装-MySQL8-0-13"><span class="nav-number">18.</span> <span class="nav-text">安装 MySQL8.0.13</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#查询指定数据库的所有表名称"><span class="nav-number">19.</span> <span class="nav-text">查询指定数据库的所有表名称</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL-分区表"><span class="nav-number">20.</span> <span class="nav-text">MySQL 分区表</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#limit优化"><span class="nav-number">21.</span> <span class="nav-text">limit优化</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#insert"><span class="nav-number">22.</span> <span class="nav-text">insert</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#bindParam-和-bindValue"><span class="nav-number">23.</span> <span class="nav-text">bindParam 和 bindValue</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#行列转换"><span class="nav-number">24.</span> <span class="nav-text">行列转换</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL密码"><span class="nav-number">25.</span> <span class="nav-text">MySQL密码</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#导出表数据"><span class="nav-number">26.</span> <span class="nav-text">导出表数据</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#从数据库中获取随机的数据"><span class="nav-number">27.</span> <span class="nav-text">从数据库中获取随机的数据</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#mysql5-7-datetime-默认值为‘0000-00-00-00-00-00’值无法创建问题解决"><span class="nav-number">28.</span> <span class="nav-text">mysql5.7 datetime 默认值为‘0000-00-00 00:00:00’值无法创建问题解决</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Redis-分布式锁"><span class="nav-number">29.</span> <span class="nav-text">Redis 分布式锁</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#redis-cli"><span class="nav-number">30.</span> <span class="nav-text">redis-cli</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#每个分组的最后一条记录"><span class="nav-number">31.</span> <span class="nav-text">每个分组的最后一条记录</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#超过经理收入的员工"><span class="nav-number">32.</span> <span class="nav-text">超过经理收入的员工</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL-之事务隔离级别"><span class="nav-number">33.</span> <span class="nav-text">MySQL 之事务隔离级别</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL性能突发事件问题排查技巧"><span class="nav-number">34.</span> <span class="nav-text">MySQL性能突发事件问题排查技巧</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Mysql-批量写入数据"><span class="nav-number">35.</span> <span class="nav-text">Mysql 批量写入数据</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Redis延时队列"><span class="nav-number">36.</span> <span class="nav-text">Redis延时队列</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#redis-分布式锁"><span class="nav-number">37.</span> <span class="nav-text">redis 分布式锁</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#redis-无法启动"><span class="nav-number">38.</span> <span class="nav-text">redis 无法启动</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#redis-导出-导入"><span class="nav-number">39.</span> <span class="nav-text">redis 导出 导入</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#优化not-in-和-lt-gt-查询"><span class="nav-number">40.</span> <span class="nav-text">优化not in 和&lt;&gt;查询</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Redis的n种妙用"><span class="nav-number">41.</span> <span class="nav-text">Redis的n种妙用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#防止库存超卖"><span class="nav-number">42.</span> <span class="nav-text">防止库存超卖</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Redis管道提升性能"><span class="nav-number">43.</span> <span class="nav-text">Redis管道提升性能</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#处理重复数据"><span class="nav-number">44.</span> <span class="nav-text">处理重复数据</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#lua-抢购场景"><span class="nav-number">45.</span> <span class="nav-text">lua 抢购场景</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#缓存与数据库双写一致性问题"><span class="nav-number">46.</span> <span class="nav-text">缓存与数据库双写一致性问题</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MongoDB读写分离"><span class="nav-number">47.</span> <span class="nav-text">MongoDB读写分离</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Laravel-分组获取最新记录"><span class="nav-number">48.</span> <span class="nav-text">Laravel 分组获取最新记录</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#将分组无结果的记录显示为0"><span class="nav-number">49.</span> <span class="nav-text">将分组无结果的记录显示为0</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MISCONF-Redis-is-configured-to-save-RDB-snapshots"><span class="nav-number">50.</span> <span class="nav-text">MISCONF Redis is configured to save RDB snapshots</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL数据库主从复制"><span class="nav-number">51.</span> <span class="nav-text">MySQL数据库主从复制</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Redis-快速实现签到统计"><span class="nav-number">52.</span> <span class="nav-text">Redis 快速实现签到统计</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL分组查询TOP-N的实践和踩坑"><span class="nav-number">53.</span> <span class="nav-text">MySQL分组查询TOP N的实践和踩坑</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#case-when"><span class="nav-number">54.</span> <span class="nav-text">case when</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#mysql-replace-into-坑"><span class="nav-number">55.</span> <span class="nav-text">mysql replace into 坑</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#类型转换对-MySQL-选择索引的影响"><span class="nav-number">56.</span> <span class="nav-text">类型转换对 MySQL 选择索引的影响</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#redis-keys-scan"><span class="nav-number">57.</span> <span class="nav-text">redis keys scan</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#mysql5-7Incorrect-datetime-value-‘0000-00-00-00-00-00’-for-column"><span class="nav-number">58.</span> <span class="nav-text">mysql5.7Incorrect datetime value: ‘0000-00-00 00:00:00’ for column</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#mysql的limit进行分页时出现重复"><span class="nav-number">59.</span> <span class="nav-text">mysql的limit进行分页时出现重复</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#预估-Mysql-数据表的数据大小和索引大小"><span class="nav-number">60.</span> <span class="nav-text">预估 Mysql 数据表的数据大小和索引大小</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#mysql-limit查询优化方法"><span class="nav-number">61.</span> <span class="nav-text">mysql limit查询优化方法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#FOUND-ROWS"><span class="nav-number">62.</span> <span class="nav-text">FOUND_ROWS()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#left-join-on-where"><span class="nav-number">63.</span> <span class="nav-text">left join on where</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#如何索引-JSON-字段"><span class="nav-number">64.</span> <span class="nav-text">如何索引 JSON 字段</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#length-检测-vachar-字节长度"><span class="nav-number">65.</span> <span class="nav-text">length 检测 vachar 字节长度</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#浅析乐观锁与悲观锁"><span class="nav-number">66.</span> <span class="nav-text">浅析乐观锁与悲观锁</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#mysql-8-0-使用简单密码"><span class="nav-number">67.</span> <span class="nav-text">mysql 8.0 使用简单密码</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Mysql-批量更新多行"><span class="nav-number">68.</span> <span class="nav-text">Mysql 批量更新多行</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL中的注释符"><span class="nav-number">69.</span> <span class="nav-text">MySQL中的注释符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#获取元数据"><span class="nav-number">70.</span> <span class="nav-text">获取元数据</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#SQL-注入"><span class="nav-number">71.</span> <span class="nav-text">SQL 注入</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#取出一组热门作者及他们最近发表的-3-篇文章"><span class="nav-number">72.</span> <span class="nav-text">取出一组热门作者及他们最近发表的 3 篇文章</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#多更新"><span class="nav-number">73.</span> <span class="nav-text">多更新</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL-调优经历"><span class="nav-number">74.</span> <span class="nav-text">MySQL 调优经历</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#exists"><span class="nav-number">75.</span> <span class="nav-text">exists</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#批量更新所有字段字符集"><span class="nav-number">76.</span> <span class="nav-text">批量更新所有字段字符集</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#每门科目成绩前三的数据"><span class="nav-number">77.</span> <span class="nav-text">每门科目成绩前三的数据</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#删除表中重复数据，并保留一条"><span class="nav-number">78.</span> <span class="nav-text">删除表中重复数据，并保留一条</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#并列排名和顺序排名查询"><span class="nav-number">79.</span> <span class="nav-text">并列排名和顺序排名查询</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL-分页数据错乱重复"><span class="nav-number">80.</span> <span class="nav-text">MySQL 分页数据错乱重复</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL-闪回工具之-binlog2sql"><span class="nav-number">81.</span> <span class="nav-text">MySQL 闪回工具之 binlog2sql</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#You-can’t-specify-target-table-for-update"><span class="nav-number">82.</span> <span class="nav-text">You can’t specify target table for update</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#分组无数据查询填充0"><span class="nav-number">83.</span> <span class="nav-text">分组无数据查询填充0</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#保留-IN-中的顺序"><span class="nav-number">84.</span> <span class="nav-text">保留 IN 中的顺序</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#分组取前3"><span class="nav-number">85.</span> <span class="nav-text">分组取前3</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#升级mongodb3"><span class="nav-number">86.</span> <span class="nav-text">升级mongodb3</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Mysql-大表分页查询优化"><span class="nav-number">87.</span> <span class="nav-text">Mysql 大表分页查询优化</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#不区分大小写"><span class="nav-number">88.</span> <span class="nav-text">不区分大小写</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL-备份"><span class="nav-number">89.</span> <span class="nav-text">MySQL 备份</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#groupBy-分组统计"><span class="nav-number">90.</span> <span class="nav-text">groupBy 分组统计</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#导入文件"><span class="nav-number">91.</span> <span class="nav-text">导入文件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#关联查询"><span class="nav-number">92.</span> <span class="nav-text">关联查询</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL大数据分页"><span class="nav-number">93.</span> <span class="nav-text">MySQL大数据分页</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL-索引使用策略及优化"><span class="nav-number">94.</span> <span class="nav-text">MySQL 索引使用策略及优化</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#datetime-默认值为‘0000-00-00-00-00-00’值无法创建"><span class="nav-number">95.</span> <span class="nav-text">datetime 默认值为‘0000-00-00 00:00:00’值无法创建</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#删除重复数据"><span class="nav-number">96.</span> <span class="nav-text">删除重复数据</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#每个用户最新一条"><span class="nav-number">97.</span> <span class="nav-text">每个用户最新一条</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#mysql索引测试"><span class="nav-number">98.</span> <span class="nav-text">mysql索引测试</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL-避坑宝典"><span class="nav-number">99.</span> <span class="nav-text">MySQL 避坑宝典</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#数据中的排名"><span class="nav-number">100.</span> <span class="nav-text">数据中的排名</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#树查询"><span class="nav-number">101.</span> <span class="nav-text">树查询</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#profile-工具"><span class="nav-number">102.</span> <span class="nav-text">profile 工具</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#limit-语句的索引使用优化"><span class="nav-number">103.</span> <span class="nav-text">limit 语句的索引使用优化</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#group-by-城市行业后获取工资最低"><span class="nav-number">104.</span> <span class="nav-text">group by 城市行业后获取工资最低</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#每个司机今天最早的一笔订单"><span class="nav-number">105.</span> <span class="nav-text">每个司机今天最早的一笔订单</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#删除重复"><span class="nav-number">106.</span> <span class="nav-text">删除重复</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL-通过-binlog-恢复数据"><span class="nav-number">107.</span> <span class="nav-text">MySQL 通过 binlog 恢复数据</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL-8-0-加密方式不兼容"><span class="nav-number">108.</span> <span class="nav-text">MySQL 8.0 加密方式不兼容</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL-安装常见错误"><span class="nav-number">109.</span> <span class="nav-text">MySQL 安装常见错误</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#数据库脏读"><span class="nav-number">110.</span> <span class="nav-text">数据库脏读</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#创建外键报错"><span class="nav-number">111.</span> <span class="nav-text">创建外键报错</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#并发测试"><span class="nav-number">112.</span> <span class="nav-text">并发测试</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#mysql-update超卖"><span class="nav-number">113.</span> <span class="nav-text">mysql update超卖</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#mysql5-7-datetime-默认值为‘0000-00-00-00-00-00’值无法创建"><span class="nav-number">114.</span> <span class="nav-text">mysql5.7 datetime 默认值为‘0000-00-00 00:00:00’值无法创建</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#INFORMATION-SCHEMA"><span class="nav-number">115.</span> <span class="nav-text">INFORMATION_SCHEMA</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Got-error-134-from-storage-engine"><span class="nav-number">116.</span> <span class="nav-text">Got error 134 from storage engine</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL批量更新与插入"><span class="nav-number">117.</span> <span class="nav-text">MySQL批量更新与插入</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#恢复误删的数据库"><span class="nav-number">118.</span> <span class="nav-text">恢复误删的数据库</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#show-processlist-神器"><span class="nav-number">119.</span> <span class="nav-text">show processlist 神器</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#like-条件的优化"><span class="nav-number">120.</span> <span class="nav-text">like 条件的优化</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL事务隔离"><span class="nav-number">121.</span> <span class="nav-text">MySQL事务隔离</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#后台权限表"><span class="nav-number">122.</span> <span class="nav-text">后台权限表</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#取分组数据的前N条纪录"><span class="nav-number">123.</span> <span class="nav-text">取分组数据的前N条纪录</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL-定时备份"><span class="nav-number">124.</span> <span class="nav-text">MySQL 定时备份</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQl事务最全详解"><span class="nav-number">125.</span> <span class="nav-text">MySQl事务最全详解</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL大小写不敏感问题"><span class="nav-number">126.</span> <span class="nav-text">MySQL大小写不敏感问题</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL分页offset过大性能问题与优化"><span class="nav-number">127.</span> <span class="nav-text">MySQL分页offset过大性能问题与优化</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL-反向模糊查找"><span class="nav-number">128.</span> <span class="nav-text">MySQL 反向模糊查找</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#大表分页查询调研"><span class="nav-number">129.</span> <span class="nav-text">大表分页查询调研</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#修改密码"><span class="nav-number">130.</span> <span class="nav-text">修改密码</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Orderby-排序优化"><span class="nav-number">131.</span> <span class="nav-text">Orderby 排序优化</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#更新同一个表不同字段"><span class="nav-number">132.</span> <span class="nav-text">更新同一个表不同字段</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#慢查询分析调优工具"><span class="nav-number">133.</span> <span class="nav-text">慢查询分析调优工具</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#慢查询分析调优工具-1"><span class="nav-number">134.</span> <span class="nav-text">慢查询分析调优工具</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#索引失效"><span class="nav-number">135.</span> <span class="nav-text">索引失效</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#布尔值来作为-Group-By-Raw-条件"><span class="nav-number">136.</span> <span class="nav-text">布尔值来作为 Group By Raw 条件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#悲观锁与乐观锁"><span class="nav-number">137.</span> <span class="nav-text">悲观锁与乐观锁</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL-递归查询"><span class="nav-number">138.</span> <span class="nav-text">MySQL 递归查询</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL-行列转换"><span class="nav-number">139.</span> <span class="nav-text">MySQL 行列转换</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#MySQL-获取随机条数据"><span class="nav-number">140.</span> <span class="nav-text">MySQL 获取随机条数据</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>

<div class="copyright">&copy; <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">苏生不惑</span>

  
</div>


  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Gemini</a> v5.1.4</div>



<div>
<span id="showDays"></span>

</div>

<span id="busuanzi_container_site_pv">
   总访问量:<span id="busuanzi_value_site_pv"></span>次
</span>



  <span class="post-meta-divider">|</span>



<div class="theme-info">
  <div class="powered-by"></div>
  <span class="post-count">博客全站共773.8k字</span>
</div>
<script>
var birthDay = new Date("11/20/2018");
var now = new Date();
var duration = now.getTime() - birthDay.getTime();
var total= Math.floor(duration / (1000 * 60 * 60 * 24));
document.getElementById("showDays").innerHTML = "本站已运行 "+total+" 天";
</script>

        
<div class="busuanzi-count">
  <script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>

  
    <span class="site-uv">
      <i class="fa fa-user"></i>
      <span class="busuanzi-value" id="busuanzi_value_site_uv"></span>
      人次
    </span>
  

  
    <span class="site-pv">
      <i class="fa fa-eye"></i>
      <span class="busuanzi-value" id="busuanzi_value_site_pv"></span>
      次
    </span>
  
</div>








        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  


  











  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  

  
  
    <script type="text/javascript" src="/lib/canvas-nest/canvas-nest.min.js"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.4"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  











<script type="text/javascript">
    (function() {
        // 匿名函数，防止污染全局变量
        var utterances = document.createElement('script');
        utterances.type = 'text/javascript';
        utterances.async = true;
        utterances.setAttribute('issue-term','0')
        utterances.setAttribute('theme','')
        utterances.setAttribute('repo','sushengbuhuo/laravel_ioc_demo')
        utterances.crossorigin = 'anonymous';
        utterances.src = 'https://utteranc.es/client.js';
        // content 是要插入评论的地方
        document.getElementById('gitment-container').appendChild(utterances);
    })();
</script>


  

  <script type="text/javascript">
    // Popup Window;
    var isfetched = false;
    var isXml = true;
    // Search DB path;
    var search_path = "search.xml";
    if (search_path.length === 0) {
      search_path = "search.xml";
    } else if (/json$/i.test(search_path)) {
      isXml = false;
    }
    var path = "/" + search_path;
    // monitor main search box;

    var onPopupClose = function (e) {
      $('.popup').hide();
      $('#local-search-input').val('');
      $('.search-result-list').remove();
      $('#no-result').remove();
      $(".local-search-pop-overlay").remove();
      $('body').css('overflow', '');
    }

    function proceedsearch() {
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay"></div>')
        .css('overflow', 'hidden');
      $('.search-popup-overlay').click(onPopupClose);
      $('.popup').toggle();
      var $localSearchInput = $('#local-search-input');
      $localSearchInput.attr("autocapitalize", "none");
      $localSearchInput.attr("autocorrect", "off");
      $localSearchInput.focus();
    }

    // search function;
    var searchFunc = function(path, search_id, content_id) {
      'use strict';

      // start loading animation
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay">' +
          '<div id="search-loading-icon">' +
          '<i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>' +
          '</div>' +
          '</div>')
        .css('overflow', 'hidden');
      $("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center');

      $.ajax({
        url: path,
        dataType: isXml ? "xml" : "json",
        async: true,
        success: function(res) {
          // get the contents from search data
          isfetched = true;
          $('.popup').detach().appendTo('.header-inner');
          var datas = isXml ? $("entry", res).map(function() {
            return {
              title: $("title", this).text(),
              content: $("content",this).text(),
              url: $("url" , this).text()
            };
          }).get() : res;
          var input = document.getElementById(search_id);
          var resultContent = document.getElementById(content_id);
          var inputEventFunction = function() {
            var searchText = input.value.trim().toLowerCase();
            var keywords = searchText.split(/[\s\-]+/);
            if (keywords.length > 1) {
              keywords.push(searchText);
            }
            var resultItems = [];
            if (searchText.length > 0) {
              // perform local searching
              datas.forEach(function(data) {
                var isMatch = false;
                var hitCount = 0;
                var searchTextCount = 0;
                var title = data.title.trim();
                var titleInLowerCase = title.toLowerCase();
                var content = data.content.trim().replace(/<[^>]+>/g,"");
                var contentInLowerCase = content.toLowerCase();
                var articleUrl = decodeURIComponent(data.url);
                var indexOfTitle = [];
                var indexOfContent = [];
                // only match articles with not empty titles
                if(title != '') {
                  keywords.forEach(function(keyword) {
                    function getIndexByWord(word, text, caseSensitive) {
                      var wordLen = word.length;
                      if (wordLen === 0) {
                        return [];
                      }
                      var startPosition = 0, position = [], index = [];
                      if (!caseSensitive) {
                        text = text.toLowerCase();
                        word = word.toLowerCase();
                      }
                      while ((position = text.indexOf(word, startPosition)) > -1) {
                        index.push({position: position, word: word});
                        startPosition = position + wordLen;
                      }
                      return index;
                    }

                    indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false));
                    indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false));
                  });
                  if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
                    isMatch = true;
                    hitCount = indexOfTitle.length + indexOfContent.length;
                  }
                }

                // show search results

                if (isMatch) {
                  // sort index by position of keyword

                  [indexOfTitle, indexOfContent].forEach(function (index) {
                    index.sort(function (itemLeft, itemRight) {
                      if (itemRight.position !== itemLeft.position) {
                        return itemRight.position - itemLeft.position;
                      } else {
                        return itemLeft.word.length - itemRight.word.length;
                      }
                    });
                  });

                  // merge hits into slices

                  function mergeIntoSlice(text, start, end, index) {
                    var item = index[index.length - 1];
                    var position = item.position;
                    var word = item.word;
                    var hits = [];
                    var searchTextCountInSlice = 0;
                    while (position + word.length <= end && index.length != 0) {
                      if (word === searchText) {
                        searchTextCountInSlice++;
                      }
                      hits.push({position: position, length: word.length});
                      var wordEnd = position + word.length;

                      // move to next position of hit

                      index.pop();
                      while (index.length != 0) {
                        item = index[index.length - 1];
                        position = item.position;
                        word = item.word;
                        if (wordEnd > position) {
                          index.pop();
                        } else {
                          break;
                        }
                      }
                    }
                    searchTextCount += searchTextCountInSlice;
                    return {
                      hits: hits,
                      start: start,
                      end: end,
                      searchTextCount: searchTextCountInSlice
                    };
                  }

                  var slicesOfTitle = [];
                  if (indexOfTitle.length != 0) {
                    slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle));
                  }

                  var slicesOfContent = [];
                  while (indexOfContent.length != 0) {
                    var item = indexOfContent[indexOfContent.length - 1];
                    var position = item.position;
                    var word = item.word;
                    // cut out 100 characters
                    var start = position - 20;
                    var end = position + 80;
                    if(start < 0){
                      start = 0;
                    }
                    if (end < position + word.length) {
                      end = position + word.length;
                    }
                    if(end > content.length){
                      end = content.length;
                    }
                    slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent));
                  }

                  // sort slices in content by search text's count and hits' count

                  slicesOfContent.sort(function (sliceLeft, sliceRight) {
                    if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
                      return sliceRight.searchTextCount - sliceLeft.searchTextCount;
                    } else if (sliceLeft.hits.length !== sliceRight.hits.length) {
                      return sliceRight.hits.length - sliceLeft.hits.length;
                    } else {
                      return sliceLeft.start - sliceRight.start;
                    }
                  });

                  // select top N slices in content

                  var upperBound = parseInt('1');
                  if (upperBound >= 0) {
                    slicesOfContent = slicesOfContent.slice(0, upperBound);
                  }

                  // highlight title and content

                  function highlightKeyword(text, slice) {
                    var result = '';
                    var prevEnd = slice.start;
                    slice.hits.forEach(function (hit) {
                      result += text.substring(prevEnd, hit.position);
                      var end = hit.position + hit.length;
                      result += '<b class="search-keyword">' + text.substring(hit.position, end) + '</b>';
                      prevEnd = end;
                    });
                    result += text.substring(prevEnd, slice.end);
                    return result;
                  }

                  var resultItem = '';

                  if (slicesOfTitle.length != 0) {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + highlightKeyword(title, slicesOfTitle[0]) + "</a>";
                  } else {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + title + "</a>";
                  }

                  slicesOfContent.forEach(function (slice) {
                    resultItem += "<a href='" + articleUrl + "'>" +
                      "<p class=\"search-result\">" + highlightKeyword(content, slice) +
                      "...</p>" + "</a>";
                  });

                  resultItem += "</li>";
                  resultItems.push({
                    item: resultItem,
                    searchTextCount: searchTextCount,
                    hitCount: hitCount,
                    id: resultItems.length
                  });
                }
              })
            };
            if (keywords.length === 1 && keywords[0] === "") {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>'
            } else if (resultItems.length === 0) {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'
            } else {
              resultItems.sort(function (resultLeft, resultRight) {
                if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
                  return resultRight.searchTextCount - resultLeft.searchTextCount;
                } else if (resultLeft.hitCount !== resultRight.hitCount) {
                  return resultRight.hitCount - resultLeft.hitCount;
                } else {
                  return resultRight.id - resultLeft.id;
                }
              });
              var searchResultList = '<ul class=\"search-result-list\">';
              resultItems.forEach(function (result) {
                searchResultList += result.item;
              })
              searchResultList += "</ul>";
              resultContent.innerHTML = searchResultList;
            }
          }

          if ('auto' === 'auto') {
            input.addEventListener('input', inputEventFunction);
          } else {
            $('.search-icon').click(inputEventFunction);
            input.addEventListener('keypress', function (event) {
              if (event.keyCode === 13) {
                inputEventFunction();
              }
            });
          }

          // remove loading animation
          $(".local-search-pop-overlay").remove();
          $('body').css('overflow', '');

          proceedsearch();
        }
      });
    }

    // handle and trigger popup window;
    $('.popup-trigger').click(function(e) {
      e.stopPropagation();
      if (isfetched === false) {
        searchFunc(path, 'local-search-input', 'local-search-result');
      } else {
        proceedsearch();
      };
    });

    $('.popup-btn-close').click(onPopupClose);
    $('.popup').click(function(e){
      e.stopPropagation();
    });
    $(document).on('keyup', function (event) {
      var shouldDismissSearchPopup = event.which === 27 &&
        $('.search-popup').is(':visible');
      if (shouldDismissSearchPopup) {
        onPopupClose();
      }
    });
  </script>





  

  

  

  
  

  

  

  

  
<script>
  ((window.gitter = {}).chat = {}).options = {
    //room替换成自己的聊天室名称即可，room的名称规则是：username/roomname
    room: 'sushengbuhuo-chat/mychat'
  };
</script>
<script src="https://sidecar.gitter.im/dist/sidecar.v1.js" async defer></script>

</body>
</html>
